package com.alibaba.citrus.cr.platform.enhance.facade.service.inventoryAllot;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.alibaba.citrus.cr.common.annotation.EpochTransactional;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.util.DateUtils;
import com.alibaba.citrus.cr.common.util.SpringContextUtil;
import com.alibaba.citrus.cr.platform.enhance.functions.inventoryAllot.*;
import com.alibaba.citrus.cr.platform.enhance.functions.inventoryAllot.entity.InventoryAllotEntity;
import com.alibaba.citrus.cr.platform.enhance.functions.inventoryAllot.factory.InventoryAllotFactory;
import com.alibaba.citrus.cr.platform.enhance.repository.InventoryAllotRepository;
import com.alibaba.citrus.cr.platform.enhance.repository.StrategyQueryRepository;
import com.alibaba.citrus.cr.sales.plan.api.salesplan.SalesPlanQueryService;
import com.alibaba.citrus.cr.sales.plan.api.setting.SalesPlanScItemQueryService;
import com.alibaba.citrus.cr.sales.plan.api.statistics.SalesPlanScItemStatQueryService;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.PageQueryPlanScItemStatRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.PageQuerySalePlanRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.QueryPlanScItemStatRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.SalesPlanScItemPageQueryRequest;
import com.alibaba.citrus.cr.sales.plan.model.enums.ContractStatDimensionEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.SalesStatBizTypeEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.StatPoolTypeEnum;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanScItemSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanStatScItemSDO;
import com.alibaba.cz.base.tool.DateFormatUtil;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.lattice2.epoch.sdk.model.Result;

import com.epoch.app.bcorder.model.dto.*;
import com.epoch.app.bcorder.model.dto.ScItemSDO;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.SalesPlanService;
import com.epoch.app.bcorder.service.UnifiedInventoryService;
import com.epoch.app.crb2btradecenter.api.orderlinequery.service.OrderLineQueryService;
import com.epoch.app.crb2btradecenter.model.dto.AmountResponse;
import com.epoch.app.crb2btradecenter.model.dto.SearchOrderLineListRequest;
import com.epoch.app.crplatformenhance.api.organizationquery.service.OrganizationQueryService;
import com.epoch.app.crplatformenhance.api.strategyquery.service.StrategyQueryService;
import com.epoch.app.crplatformenhance.dto.request.IdQueryRequest;
import com.epoch.app.crplatformenhance.enums.DimensionTypeEnum;
import com.epoch.app.crplatformenhance.enums.InventoryAllotTypeEnum;
import com.epoch.app.crplatformenhance.enums.StrategyTypeEnum;
import com.epoch.app.crplatformenhance.inventoryallot.dto.LoadRequest;
import com.epoch.app.crplatformenhance.inventoryallot.model.InventoryAllot;
import com.epoch.app.crplatformenhance.inventoryallot.service.InventoryAllotService;
import com.epoch.app.crplatformenhance.inventoryallotline.model.InventoryAllotLine;
import com.epoch.app.crplatformenhance.inventoryallotline.service.InventoryAllotLineService;
import com.epoch.app.crplatformenhance.inventoryallotlinewrite.service.InventoryAllotLineWriteService;
import com.epoch.app.crplatformenhance.inventoryallotwrite.dto.ImportAdjustedAllotLineDataRequest;
import com.epoch.app.crplatformenhance.inventoryallotwrite.service.InventoryAllotWriteService;
import com.epoch.app.crplatformenhance.model.dto.*;
import com.epoch.app.crplatformenhance.model.enums.ProportionTypeEnum;
import com.epoch.app.crplatformenhance.sdo.DimensionSDO;
import com.epoch.app.crplatformenhance.sdo.OrganizationRelationSDO;
import com.epoch.app.crplatformenhance.sdo.StrategySDO;
import com.epoch.app.crplatformenhance.service.CrPlatformEnhanceService;
import com.epoch.app.crplatformenhance.strategy.dto.QueryValidStrategyListRequest;
import com.epoch.app.crunifiedinventory.model.dto.GetListWarehouseStockRequest;
import com.epoch.app.crunifiedinventory.model.dto.WarehouseInventory;
import com.epoch.app.crunifiedinventory.service.CrUnifiedInventoryService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class InventoryAllotServiceImpl implements InventoryAllotWriteService {

    @Resource
    private CrUnifiedInventoryService crUnifiedInventoryService;

    @Resource
    private BaseDataService baseDataService;

    @Resource
    private StrategyQueryService strategyQueryService;

    @Resource
    private StrategyQueryRepository strategyQueryRepository;

    @Resource
    private SalesPlanScItemStatQueryService salesPlanScItemStatQueryService;
    @Resource
    private SalesPlanScItemQueryService salesPlanScItemQueryService;

    @Resource
    private SalesPlanQueryService salesPlanQueryService;

    @Resource
    private OrganizationQueryService organizationQueryService;

    @Resource
    private SalesPlanService salesPlanService;

    @Resource
    private OrderLineQueryService orderLineQueryService;

    @Resource
    private  InventoryAllotLineWriteService inventoryAllotLineWriteService;

    @Autowired
    private InventoryAllotService inventoryAllotService;

    @Autowired
    private InventoryAllotLineService inventoryAllotLineService;
    @Resource
    private InventoryAllotRepository inventoryAllotRepository;

    @Autowired
    private CrPlatformEnhanceService crPlatformEnhanceService;

    @Autowired
    private UnifiedInventoryService unifiedInventoryService;




    private  final static int SALES_ORG_CODE_TYPE=0;

    private  final static int DEPARTMENT_CODE_TYPE=1;

    private  final static int SALESMAN_CODE_TYPE=2;

    private  final static String MANUAL_IMPORT_FLAG="M";

    private final static String WAREHOUSE_IDS = "wareHouseIds";

    private static final String COMMA = ",";




    private static final Log log = Log.getLogger(InventoryAllotServiceImpl.class);

    //todo 查询计划货品
    private List<String> getSalesPlanItemIds(InventoryAllotDetail inventoryAllotDetail) {
        //todo 查询计划货品
        List<String> itemIds = new ArrayList<>();
        SalesPlanScItemPageQueryRequest saleScItemRequest = new SalesPlanScItemPageQueryRequest();
        saleScItemRequest.setOrgSalesOrganizationCode(inventoryAllotDetail.getOrgId());
        saleScItemRequest.setStatus(1);
        saleScItemRequest.setStart(0);
        saleScItemRequest.setLimit(1000);
        saleScItemRequest.setIsOutInvoker(true);
        //@todo SELECT GROUP_CONCAT(DISTINCT(id)) FROM ofs_forecast_order_line 拼接ID
        long startTime=System.currentTimeMillis();

        Result<PageResult<List<SalesPlanScItemSDO>>> firstResult = salesPlanScItemQueryService.pageQueryProductPlanList(saleScItemRequest);
        if (firstResult == null || firstResult.getResult() == null ||
                CollectionUtils.isEmpty(firstResult.getResult().getContent())) {
            return itemIds;
        }
        List<SalesPlanScItemSDO> totalResp=new ArrayList<>();
        int total = firstResult.getTotal();
        if (total>1000){
            int page = total / 1000;
            for (int i = 0; i < page; i++) {
                saleScItemRequest.setStart(i*1000);
                saleScItemRequest.setLimit(1000);
                Result<PageResult<List<SalesPlanScItemSDO>>> pageResultResult = salesPlanScItemQueryService.pageQueryProductPlanList(saleScItemRequest);

                if (Objects.nonNull(pageResultResult)&&Objects.nonNull(pageResultResult.getResult())&&CollectionUtils.isNotEmpty(pageResultResult.getResult().getContent())){
                    totalResp.addAll(pageResultResult.getResult().getContent())   ;
                }
            }

        }else {
            totalResp.addAll(firstResult.getResult().getContent());
        }

        Set<String> list = Nullable.stream(totalResp).map(SalesPlanScItemSDO::getScItemId).collect(Collectors.toSet());
        itemIds.addAll(list);
        log.info("库存分解-全部计划货品查询：" + JSON.toJSONString(itemIds));
        long startTime2=System.currentTimeMillis();
        log.info("查询计划货品耗时:"+(startTime2-startTime));
        return itemIds;
    }

    /**
     * //查询货品范围的库存 并累加
     *
     * @param inventoryAllotDetail
     * @return Map
     */
    private Map<String, BigDecimal> getSumItemInventory(InventoryAllotDetail inventoryAllotDetail) {
        Map<String, BigDecimal> sumScItemInventory = new HashMap<>();

        //人工导入库存货品分配
        Map<String, String> manualAllotQty = manualAllotReduceQuantity(inventoryAllotDetail);
        log.info("人工导入货品分配:" + JSONObject.toJSONString(manualAllotQty));
        List<String> itemIds = new ArrayList<>();

        //查询库存并累加
        for (WarehouseScope warehouseScope : inventoryAllotDetail.getWarehouseScopes()) {

            if (CollectionUtils.isNotEmpty(inventoryAllotDetail.getScItemScopes())) {
                //根据货品和仓库查询库存接口
                GetListWarehouseStockRequest request = new GetListWarehouseStockRequest();

                itemIds = inventoryAllotDetail.getScItemScopes().stream().map(ScItemScope::getScItemId).collect(Collectors.toList());

                request.setType("1");
                request.setGoodsIds(itemIds);
                request.setWarehouseAreaId(warehouseScope.getWarehouseId());
                request.setStart(0);
                request.setSize(1000);
                log.info("库存分解-库存查询请求：" + JSON.toJSONString(request));
                Result<List<WarehouseInventory>> listWarehouseStock = crUnifiedInventoryService.getListWarehouseStock(request);
                log.info("库存分解-库存查询响应：" + JSON.toJSONString(listWarehouseStock));
                if (listWarehouseStock.isSuccess() && CollectionUtils.isEmpty(listWarehouseStock.getResult())) {
//                    throw new FunctionException("OTS-06-005-00-15-004");
                    log.error("OTS-06-005-00-15-004","未查询到货品在对应仓库的库存数据",JSON.toJSONString(request));
                    continue;
                }
                if (!listWarehouseStock.isSuccess()) {
//                    throw new FunctionException("OTS-06-005-00-15-010");
                    log.error("OTS-06-005-00-15-010","查询库存异常",JSON.toJSONString(listWarehouseStock));
                    continue;
                }
                listWarehouseStock.getResult().forEach(result -> {
                    String scItemId = result.getGoodsId();
                    BigDecimal quantity = (new BigDecimal(result.getAvailableQuantityFormat())).setScale(0,BigDecimal.ROUND_DOWN);
                    sumScItemInventory.put(scItemId, sumScItemInventory.get(scItemId) == null ? quantity : sumScItemInventory.get(scItemId).add(quantity));
                });
            } else {
                //todo 这里应该是查询计划货品
                itemIds = getSalesPlanItemIds(inventoryAllotDetail);
                GetListWarehouseStockRequest request = new GetListWarehouseStockRequest();
                request.setType("1");
                request.setGoodsIds(itemIds);
                request.setWarehouseAreaId(warehouseScope.getWarehouseId());
                request.setSize(999);
                Result<List<WarehouseInventory>> listWarehouseStock = crUnifiedInventoryService.getListWarehouseStock(request);
                log.info("库存分解-全货品库存查询：" + JSON.toJSONString(listWarehouseStock));
                Nullable.stream(listWarehouseStock.getResult()).forEach(result -> {
                    String scItemId = result.getGoodsId();
                    BigDecimal quantity = (new BigDecimal(result.getAvailableQuantityFormat())).setScale(0,BigDecimal.ROUND_DOWN);
                    sumScItemInventory.put(scItemId, sumScItemInventory.get(scItemId) == null ? quantity : sumScItemInventory.get(scItemId).add(quantity));
                });
            }
        }
        log.info("库存分解-计划货品仓库库存累计结果：" + JSON.toJSONString(sumScItemInventory));
        if (MapUtils.isEmpty(sumScItemInventory)) {
            throw new FunctionException("OTS-06-005-00-15-004");
        }
        for (Entry<String, String> entry: manualAllotQty.entrySet()) {
            // 对应货品库存
            BigDecimal qty = sumScItemInventory.get(entry.getKey());
            String manualQty = entry.getValue();
            if (Objects.isNull(qty) || StringUtils.isEmpty(manualQty) || new BigDecimal(manualQty).compareTo(BigDecimal.ZERO) <=0) {
                continue;
            }
            if (qty.compareTo(new BigDecimal(manualQty)) < 0) {
                manualQty = qty.toString();
            }
            sumScItemInventory.put(entry.getKey(), qty.subtract(new BigDecimal(manualQty)).setScale(0,BigDecimal.ROUND_DOWN));
        }
        return sumScItemInventory;
    }

    @FacadeInvoker
    private List<String> querySaleChannelByChannel(InventoryAllotDetail inventoryAllotDetail, ChannelScope channelScope) {
        List<String> saleChannelList = new ArrayList<>();
        //查询渠道关联的所有相关组织
        /*IdQueryRequest idQueryRequest = new IdQueryRequest();
        idQueryRequest.setCode(channelScope.getChannelId());*/

        GetOrgChannelRelationByChannelRequest getOrgChannelRelationByChannelRequest = new GetOrgChannelRelationByChannelRequest();
        getOrgChannelRelationByChannelRequest.setChannelCode(channelScope.getChannelId());
        log.info("库存分解-查询业务渠道关联组织请求：" + JSON.toJSONString(getOrgChannelRelationByChannelRequest));
        Result<List<OrganizationRelationSDO>> orgChannelRelationByChannel = crPlatformEnhanceService.getOrgChannelRelationByChannel(getOrgChannelRelationByChannelRequest);
        // Result<List<OrganizationRelationSDO>> orgChannelRelationByChannelId = organizationQueryService.getOrgChannelRelationByChannelId(idQueryRequest);
        log.info("库存分解-查询业务渠道关联组织响应：" + JSON.toJSONString(orgChannelRelationByChannel));
        if (orgChannelRelationByChannel == null || CollectionUtils.isEmpty(orgChannelRelationByChannel.getResult())) {
//            throw   new FacadeException("OTS-05-001-10-16-021", channelScope.getChannelName());
            return saleChannelList;
        }
        //查询当前组织下的所有销售渠道
        List<String> orgList = orgChannelRelationByChannel.getResult().stream().map(OrganizationRelationSDO::getOrganiztionId).collect(Collectors.toList());
        IdQueryRequest saleChannelRequest = new IdQueryRequest();
        saleChannelRequest.setId(inventoryAllotDetail.getOrgId());
        saleChannelRequest.setType(105);
        log.info("库存分解-查询当前组织下的所有销售渠道请求：" + JSON.toJSONString(saleChannelRequest));
        Result<List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>> downQueryOrganization = organizationQueryService.getDownQueryOrganization(saleChannelRequest);
        log.info("库存分解-查询当前组织下的所有销售渠道响应：" + JSON.toJSONString(downQueryOrganization));
        if (downQueryOrganization == null || CollectionUtils.isEmpty(downQueryOrganization.getResult())) {
//            throw new FacadeException("OTS-05-001-10-16-020", inventoryAllotDetail.getOrgName());
            return saleChannelList;
        }

        for (com.epoch.app.crplatformenhance.sdo.OrganizationSDO organizationRelationSDO : downQueryOrganization.getResult()) {
            if (orgList.contains(organizationRelationSDO.getId())) {
                saleChannelList.add(organizationRelationSDO.getId());
            }
        }
        return saleChannelList;
    }

    //这里可以优化为批量接口 type "CHANNEL" "DEPART" "SALESMAN"
    private Map<String, BigDecimal> getDeliveryAmount(String itemId, String orgId, String dimension, InventoryAllotTypeEnum type,List<String> wareHouseList) {
        SearchOrderLineListRequest request = new SearchOrderLineListRequest();
        Calendar cale = Calendar.getInstance();
        cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 0);
        cale.set(Calendar.DAY_OF_MONTH, 1);

//        log.info("++++" + DateUtils.getFirstTime(cale.getTime()));
        //查询当前月份创建的销售订单
        request.setGmtCreateStartTime(DateUtils.getFirstTime(cale.getTime()));
        request.setWareHouseIdList(wareHouseList);

        //差量计算 当月 当前业务渠道任务量-当前组织当前业务渠道累计已发货数量
        Map<String, BigDecimal> orderDeliveryAmountMap = new HashMap<>();

        if (type.equals(InventoryAllotTypeEnum.CHANNEL)) {
            request.setChannelCodeList(Lists.newArrayList(dimension));
        }
        if (type.equals(InventoryAllotTypeEnum.DEPARTMENT)) {
            request.setDepartmentList(Lists.newArrayList(dimension));
        }
        if (type.equals(InventoryAllotTypeEnum.SALESMAN)) {
            request.setSalesmanCodeList(Lists.newArrayList(dimension));
        }
        List<String> orderTagList = new ArrayList<>();
        ;
        orderTagList.add("normal");
        request.setOrderTagList(orderTagList);
        request.setItemIdList(Lists.newArrayList(itemId));
        request.setOrganizationList(Lists.newArrayList(orgId));
        //todo 添加 组织  业务渠道 业务员  订单tag查询（排除退货 换货订单）
        log.info("库存分解-查询发货数量请求:" + JSON.toJSONString(request));
        Result<AmountResponse> result = orderLineQueryService.sumOrderDeliveryAmount(request);
        log.info("库存分解-查询发货数量响应:" + JSON.toJSONString(result));
        AmountResponse amountResponse = result.getResult();
        if (result != null && amountResponse != null) {
            //渠道对应的货品发货数量
            orderDeliveryAmountMap.put(dimension + ":" + itemId, new BigDecimal(amountResponse.getBasicDeliveryAmountTotal()));
        }
        return orderDeliveryAmountMap;
    }

    @FacadeInvoker
    @Override
    public Result<Boolean> executeInventoryAllot(ExecuteInventoryAllotRequest executeInventoryAllotRequest) {

        if (StringUtils.isBlank(executeInventoryAllotRequest.getInventoryAllotTime())) {
            return Result.fail("OTS-06-001-00-15-001", "请选择库存分解日期");
        }
        if (StringUtils.isBlank(executeInventoryAllotRequest.getOrganizationCode())) {
            return Result.fail("OTS-06-001-00-15-003", "请指定组织进行分解");
        }

        boolean limitSwitch= !Objects.isNull(executeInventoryAllotRequest.getLimitSwitch()) && executeInventoryAllotRequest.getLimitSwitch();
        long startTime = System.currentTimeMillis();
        log.info("每日库存分解开始:" + JSONObject.toJSONString(executeInventoryAllotRequest));
        QueryValidStrategyListRequest strategyListRequest = new QueryValidStrategyListRequest();
        strategyListRequest.setValidTimePoint(new Date());
        strategyListRequest.setType(StrategyTypeEnum.DAILY_INVENTORY.getCode());
        strategyListRequest.setOrganizationCode(executeInventoryAllotRequest.getOrganizationCode());
        strategyListRequest.setStatus("1");
        List<StrategySDO> strategySDOS = strategyQueryRepository.queryValidStrategyList(strategyListRequest);
        if (CollectionUtils.isEmpty(strategySDOS)) {
            return Result.fail("OTS-06-001-00-15-002", "没有可进行分配的库存策略");
        }
        try {
            List<InventoryAllotDetail> inventoryAllotDetails = converterDetail(strategySDOS);
            log.info("每日库存分解详情:" + JSONObject.toJSONString(inventoryAllotDetails));

            for (InventoryAllotDetail inventoryAllotDetail : inventoryAllotDetails) {
                InventoryAllotSDO inventoryAllotSDO = new InventoryAllotSDO();
                inventoryAllotSDO.setLimitSwitch(limitSwitch);
                inventoryAllotSDO.setDistributionType(inventoryAllotDetail.getDimensionType());
                inventoryAllotSDO.setDistributionId(inventoryAllotDetail.getStrategyId());
                inventoryAllotSDO.setOrganizationCode(inventoryAllotDetail.getOrgId());

                BaselineGetOrganizationByIdsRequest organizationByIdsRequest = new BaselineGetOrganizationByIdsRequest();
                List<String> saleIds = new ArrayList<>();
                saleIds.add(inventoryAllotSDO.getOrganizationCode());
                organizationByIdsRequest.setIds(saleIds);
                Map saleMap = (Map) baseDataService.baselineGetOrganizationByIds(organizationByIdsRequest);
                JSONArray jsonArray = JSONObject.parseObject(JSONObject.toJSONString(saleMap)).getJSONArray("result");
                if (CollectionUtils.isNotEmpty(jsonArray)) {
                    JSONObject organizationSDO = jsonArray.getJSONObject(0).getJSONObject("organizationSDO");
                    inventoryAllotSDO.setOrganizationName(organizationSDO.getString("name"));
                }
                inventoryAllotSDO.setValidEndTime(inventoryAllotDetail.getValidEndTime());
                inventoryAllotSDO.setValidBeginTime(inventoryAllotDetail.getValidBeginTime());
                inventoryAllotSDO.setDailyBeginTime(inventoryAllotDetail.getDailyBeginTime());
                inventoryAllotSDO.setDailyEndTime(inventoryAllotDetail.getDailyEndTime());
                inventoryAllotSDO.setInventoryAllotTime(executeInventoryAllotRequest.getInventoryAllotTime() == null ? null : DateFormatUtil.parseSimpleDateFormat(executeInventoryAllotRequest.getInventoryAllotTime()));
                //1、查询并累加货品库存
                List<String> wareHouseIds = inventoryAllotDetail.getWarehouseScopes().stream().map(WarehouseScope::getWarehouseId).collect(Collectors.toList());
                String features = inventoryAllotSDO.getFeatures();
                Map<String, String> featureMap = new HashMap<>();
                if (StringUtils.isNotBlank(features)) {
                    featureMap = JSONObject.parseObject(features, new TypeReference<Map<String, String>>() {
                    });
                }
                featureMap.put(WAREHOUSE_IDS, JSONObject.toJSONString(wareHouseIds));
                inventoryAllotSDO.setFeatures(JSONObject.toJSONString(featureMap));
                long startTime4=System.currentTimeMillis();
                Map<String, BigDecimal> sumScItemInventory = getSumItemInventory(inventoryAllotDetail);
                log.info("查询并累加货品库存,耗时:"+ (System.currentTimeMillis() - startTime4));

                Map<String, Double> percentMap = new HashMap<>();
                Map<String, Double> diffMap = new HashMap<>();
                Map<String, Double> planMap = new HashMap<>();
                Map<String, Double> budgetMap = new HashMap<>();
                Map<String, Double> taskMap = new HashMap<>();


                //根据组织查询有效回复策略，并计算回复比例
                //inventoryAllotDetail.getOrgId();
                //库存分配比例
                BigDecimal percent = BigDecimal.valueOf(inventoryAllotDetail.getPercent());
                List<InventoryAllotLineSDO> inventoryAllotLineSDOS = new ArrayList<>();

                DimensionSDO dimensionSDO = getDimensionSDO(inventoryAllotDetail);
                log.info("回复计算策略:" + JSONObject.toJSONString(dimensionSDO));
                //获取所有维度集合的月度 计划


                Map<String,List<String>> bizChannelMap=new HashMap<>();
                List<ChannelScope> channelIds = inventoryAllotDetail.getChannelScopes();
                List<String> salesChannelIds =new ArrayList<>();
                List<String> departmentIds = inventoryAllotDetail.getDepartmentScopes().stream().map(DepartmentScope::getDepartmentId).collect(Collectors.toList());
                List<String> salesmenIds = inventoryAllotDetail.getSalesmanScopes().stream().map(SalesmanScope::getSalesmanId).collect(Collectors.toList());

                //渠道维度月度计划 @todo 待优化批量查询
                Nullable.stream(channelIds).forEach(o->{
                    List<String> list = querySaleChannelByChannel(inventoryAllotDetail, o);
                    salesChannelIds.addAll(list);
                    bizChannelMap.put(o.getChannelId(),list);
                });
                long startTime11=System.currentTimeMillis();

                Map<String, Map<String, List<SalesPlanStatScItemSDO>>> channelPlanMap = new HashMap<>();

                if (CollectionUtils.isNotEmpty(salesChannelIds)){
                    channelPlanMap = batchGetSalesPlanStatScItemSDOAll(inventoryAllotDetail, salesChannelIds, SalesStatBizTypeEnum.SALES_CHANNEL.getBizType());
                }
                //部门维度月度计划
                Map<String, Map<String, List<SalesPlanStatScItemSDO>>> departmentPlanMap = new HashMap<>();
                if (CollectionUtils.isNotEmpty(departmentIds)){
                    departmentPlanMap = batchGetSalesPlanStatScItemSDOAll(inventoryAllotDetail, departmentIds, SalesStatBizTypeEnum.SALES_DEPARTMENT.getBizType());
                }
                //业务员维度月度计划
                Map<String, Map<String, List<SalesPlanStatScItemSDO>>> salesmenPlanMap = new HashMap<>();
                if (CollectionUtils.isNotEmpty(salesmenIds)){
                    salesmenPlanMap = batchGetSalesPlanStatScItemSDOAll(inventoryAllotDetail, salesmenIds, SalesStatBizTypeEnum.SALESMAN.getBizType());
                }


                //合同量月度计划映射(渠道)
                Map<String, Map<String, List<MonthContractAndRollingCountResponse>>> scItemContractPlanChannel = null;
                if (CollectionUtils.isNotEmpty(salesChannelIds)){
                    scItemContractPlanChannel = getScItemContractPlan(ContractStatDimensionEnum.SALES_CHANNEL_SC_ITEM, new ArrayList<>(sumScItemInventory.keySet()), salesChannelIds);
                }

                //合同量月度计划映射(部门)
                Map<String, Map<String, List<MonthContractAndRollingCountResponse>>> scItemContractPlanDepartment=null ;
                if (CollectionUtils.isNotEmpty(departmentIds)){
                    scItemContractPlanDepartment = getScItemContractPlan(ContractStatDimensionEnum.DEPARTMENT_SC_ITEM, new ArrayList<>(sumScItemInventory.keySet()), departmentIds);
                }
                //合同量月度计划映射(业务员)
                Map<String, Map<String, List<MonthContractAndRollingCountResponse>>> scItemContractPlanSalesmen=null ;
                if (CollectionUtils.isNotEmpty(salesmenIds)) {
                    scItemContractPlanSalesmen = getScItemContractPlan(ContractStatDimensionEnum.EMPLOYEE_SC_ITEM, new ArrayList<>(sumScItemInventory.keySet()), salesmenIds);
                }

                log.info("批量查询所有月度计划耗时:"+(System.currentTimeMillis()-startTime11));

                //查询货品名称和库存单位

                long scItemStartTime=System.currentTimeMillis();
                SearchScItemRequest scItemRequest = new SearchScItemRequest();
                Map<String, List<String>> searchReq = new HashMap<>();
                searchReq.put("scItemIds", new ArrayList<>(sumScItemInventory.keySet()));
                scItemRequest.setSearchReqDTO(searchReq);
                scItemRequest.setPageNum(1);
                scItemRequest.setPageSize(2000);
                log.info("库存分解-查询货品信息请求：" + JSON.toJSONString(scItemRequest));
                Result<List<ScItemSDO>> searchScItemList = baseDataService.searchScItem(scItemRequest);
                log.info("库存分解-查询货品信息响应：" + JSON.toJSONString(searchScItemList));
                if (searchScItemList == null || CollectionUtils.isEmpty(searchScItemList.getResult())) {
                    log.error("库存分解-执行比例计算时货品未查到：" + JSON.toJSONString(searchScItemList));
                    return null;
                }
                Map<String, ScItemSDO> scItemSDOMap = Nullable.stream(searchScItemList.getResult()).collect(Collectors.toMap(ScItemSDO::getScItemId, Function.identity()));

                log.info("库存分解-查询货品信息耗时:"+(System.currentTimeMillis()-scItemStartTime));

                //将货品库存循环处理
                for (Entry<String, BigDecimal> entryInventory : sumScItemInventory.entrySet()) {
                    long startTime5=System.currentTimeMillis();
                    String k = entryInventory.getKey();
                    //如果是分解策略是渠道配置
                    if (CollectionUtils.isNotEmpty(inventoryAllotDetail.getChannelScopes())) {
                        //差量比例
                        if ("1".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            //货品所有渠道/所有部门/所有业务员的累计月度计划量
                            Map<String, BigDecimal> scItemTaskTotal = new HashMap<>();
                            //货品+渠道/部门/业务员的月度计划量
                            Map<String, BigDecimal> scItemTaskSingle = new HashMap<>();


                            //循环处理渠道 货品月度计划
                            for (ChannelScope channelScope : inventoryAllotDetail.getChannelScopes()) {
                               List<String> saleChannelList = bizChannelMap.get(channelScope.getChannelId());
                               // log.info("业务渠道" + channelScope.getChannelName() + "查询销售渠道:" + JSON.toJSONString(saleChannelList));
                                int taskCount = 0;
                                List<SalesPlanStatScItemSDO> salesPlanStatScItemSDOS=new ArrayList<>();
                                Map<String, List<SalesPlanStatScItemSDO>> stringListMap = channelPlanMap.get(k);
                                if (CollectionUtils.isNotEmpty(saleChannelList)&&MapUtils.isNotEmpty(stringListMap)) {
                                   // List<SalesPlanStatScItemSDO> salesPlanStatScItemSDOS = batchChannelGetSalesPlanStatScItemSDO(inventoryAllotDetail, k, saleChannelList);

                                for (String s : saleChannelList) {
                                    if (CollectionUtils.isNotEmpty(stringListMap.get(s))){
                                        salesPlanStatScItemSDOS.addAll(stringListMap.get(s));
                                    }
                                }
                                taskCount= Nullable.stream(salesPlanStatScItemSDOS).mapToInt(s -> s.getTaskCount() == null ? 0 : s.getTaskCount()).sum();
                                    //任务量-发货数量    某个渠道的差量 scItemTaskSingle - 总差量 scItemTaskTotal
                                    Map<String, BigDecimal> orderDeliveryMap = getDeliveryAmount(k, inventoryAllotDetail.getOrgId(), channelScope.getChannelId(), InventoryAllotTypeEnum.CHANNEL,wareHouseIds);
                                    BigDecimal taskDelta = new BigDecimal(taskCount).subtract(orderDeliveryMap.get(channelScope.getChannelId() + ":" + k) == null ? BigDecimal.valueOf(0) : orderDeliveryMap.get(channelScope.getChannelId() + ":" + k));
                                    if (taskDelta.compareTo(new BigDecimal("0")) < 0) {
                                        taskDelta = new BigDecimal("0");
                                    }
                                    scItemTaskTotal.put(k, (scItemTaskTotal.get(k) == null ? taskDelta : scItemTaskTotal.get(k).add(taskDelta)));
                                    scItemTaskSingle.put(channelScope.getChannelId() + ":" + k, taskDelta);
                                }

                            }
                            log.info("渠道维度-规则值:"+dimensionSDO.getRuleValue()+"||差量:scItemTaskSingle:" + JSON.toJSONString(scItemTaskSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemTaskTotal));
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemTaskSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemTaskTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemTaskTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent = (stringIntegerEntry.getValue().divide(scItemTaskTotal.get(scItemId),4,BigDecimal.ROUND_DOWN));
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                diffMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }
                        }

                        //计划量占比
                        if ("2".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            //货品所有渠道/所有部门/所有业务员的累计月度计划量
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            //货品+渠道/部门/业务员的月度计划量
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                            //循环处理渠道 货品月度计划
                            for (ChannelScope channelScope : inventoryAllotDetail.getChannelScopes()) {
                                List<String> saleChannelList = bizChannelMap.get(channelScope.getChannelId());
                                List<SalesPlanStatScItemSDO> salesPlanStatScItemSDOS=new ArrayList<>();
                                Map<String, List<SalesPlanStatScItemSDO>> stringListMap = channelPlanMap.get(k);

                                int monthCount=0;
                                if (CollectionUtils.isNotEmpty(saleChannelList)&&MapUtils.isNotEmpty(stringListMap)) {
                                    for (String s : saleChannelList) {
                                        if (CollectionUtils.isNotEmpty(stringListMap.get(s))){
                                            salesPlanStatScItemSDOS.addAll(stringListMap.get(s));
                                        }
                                    }
                                    monthCount= Nullable.stream(salesPlanStatScItemSDOS).mapToInt(s -> s.getMonthCount() == null ? 0 : s.getMonthCount()).sum();
                                }
                                scItemSalePlanTotal.put(k, (scItemSalePlanTotal.get(k) == null ? new BigDecimal(monthCount) : scItemSalePlanTotal.get(k).add(new BigDecimal( monthCount))));
                                scItemSalePlanSingle.put(channelScope.getChannelId() + ":" + k, new BigDecimal(monthCount));

                            }
                            log.info("渠道维度-规则值:"+dimensionSDO.getRuleValue()+"||计划量:scItemSalePlanSingle:" + JSON.toJSONString(scItemSalePlanSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemSalePlanTotal));

                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemSalePlanTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemSalePlanTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent = stringIntegerEntry.getValue().divide(scItemSalePlanTotal.get(scItemId),4,BigDecimal.ROUND_DOWN);
//                                        stringIntegerEntry.getValue() / scItemSalePlanTotal.get(scItemId);
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                planMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }

                        }

                        //预算占比
                        if ("3".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            //货品所有渠道/所有部门/所有业务员的累计月度计划量
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            //货品+渠道/部门/业务员的月度计划量
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                            //循环处理渠道 货品月度计划
                            for (ChannelScope channelScope : inventoryAllotDetail.getChannelScopes()) {
                                List<String> saleChannelList = bizChannelMap.get(channelScope.getChannelId());
                                log.info("库存分解-业务渠道" + channelScope.getChannelName() + "查询销售渠道:" + JSON.toJSONString(saleChannelList));
//                            AtomicReference<Integer> monthCount = new AtomicReference<>(0);


                                Integer monthContractCount = 0;
                                if (CollectionUtils.isNotEmpty(saleChannelList)&&Objects.nonNull(scItemContractPlanChannel) &&MapUtils.isNotEmpty(scItemContractPlanChannel.get(k)) ) {
                                    List<MonthContractAndRollingCountResponse> bizChannelList=new ArrayList<>();
                                    Map<String, List<MonthContractAndRollingCountResponse>> stringListMap = scItemContractPlanChannel.get(k);
                                    for (String salesChannelId : saleChannelList) {
                                        if (CollectionUtils.isNotEmpty(stringListMap.get(salesChannelId))){
                                            bizChannelList.addAll(stringListMap.get(salesChannelId));
                                        }

                                    }
                                    log.info("库存分解-业务渠道"+channelScope.getChannelName()+"合同量："+JSON.toJSONString(bizChannelList));
                                    monthContractCount = Nullable.stream(bizChannelList).mapToInt(mon -> mon.getMonthContractCount() == null ? 0 : mon.getMonthContractCount()).sum();
                                }

                                scItemSalePlanTotal.put(k, (scItemSalePlanTotal.get(k) == null ? new BigDecimal(monthContractCount) : scItemSalePlanTotal.get(k).add(new BigDecimal(monthContractCount))));
                                scItemSalePlanSingle.put(channelScope.getChannelId() + ":" + k, new BigDecimal(monthContractCount));
                            }
                            log.info("渠道维度-规则值:"+dimensionSDO.getRuleValue()+"||预算:scItemSalePlanSingle:" + JSON.toJSONString(scItemSalePlanSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemSalePlanTotal));
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemSalePlanTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemSalePlanTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent = stringIntegerEntry.getValue().divide(scItemSalePlanTotal.get(scItemId),4,BigDecimal.ROUND_DOWN);
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                budgetMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }

                        }
                        //任务量占比
                        if ("4".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            //货品所有渠道/所有部门/所有业务员的累计月度计划量
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            //货品+渠道/部门/业务员的月度计划量
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                            //循环处理渠道 货品月度计划
                            for (ChannelScope channelScope : inventoryAllotDetail.getChannelScopes()) {
                                List<String> saleChannelList = bizChannelMap.get(channelScope.getChannelId());
                                List<SalesPlanStatScItemSDO> salesPlanStatScItemSDOS=new ArrayList<>();
                                Map<String, List<SalesPlanStatScItemSDO>> stringListMap = channelPlanMap.get(k);
                                int taskCount=0;
                                if (CollectionUtils.isNotEmpty(saleChannelList)&&MapUtils.isNotEmpty(stringListMap)) {
                                    for (String s : saleChannelList) {
                                        if (CollectionUtils.isNotEmpty(stringListMap.get(s))){
                                            salesPlanStatScItemSDOS.addAll(stringListMap.get(s));
                                        }
                                    }
                                    // List<SalesPlanStatScItemSDO> salesPlanStatScItemSDOS = batchChannelGetSalesPlanStatScItemSDO(inventoryAllotDetail, k, saleChannelList);
                                    taskCount= Nullable.stream(salesPlanStatScItemSDOS).mapToInt(s -> s.getTaskCount() == null ? 0 : s.getTaskCount()).sum();

                                }
                                scItemSalePlanTotal.put(k, (scItemSalePlanTotal.get(k) == null ? new BigDecimal(taskCount) : scItemSalePlanTotal.get(k).add(new BigDecimal(taskCount))));
                                scItemSalePlanSingle.put(channelScope.getChannelId() + ":" + k, new BigDecimal(taskCount));
                            }
                            log.info("渠道维度-规则值:"+dimensionSDO.getRuleValue()+"||任务量:scItemSalePlanSingle:" + JSON.toJSONString(scItemSalePlanSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemSalePlanTotal));
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemSalePlanTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemSalePlanTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent =  (stringIntegerEntry.getValue().divide(scItemSalePlanTotal.get(scItemId),4,BigDecimal.ROUND_DOWN)) ;
//                              double planPercent = (double) stringIntegerEntry.getValue() / scItemSalePlanTotal.get(scItemId);
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                taskMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }
                        }

                        //综合占比
                        if ("5".equals(dimensionSDO.getRuleValue())) {
                            //货品所有渠道/所有部门/所有业务员的累计月度计划量
                            Map<String, Integer> scItemSalePlanTotal = new HashMap<>();
                            //货品+渠道/部门/业务员的月度计划量
                            Map<String, Integer> scItemSalePlanSingle = new HashMap<>();
                            Map<String, String> map = JSONObject.parseObject(dimensionSDO.getDetails(), Map.class);
                            String BR = map.get(ProportionTypeEnum.BUDGET_RATIO.getCode());//预算
                            String PR = map.get(ProportionTypeEnum.PLAN_RATIO.getCode());//计划量
                            String DR = map.get(ProportionTypeEnum.DIFFERENCE_RATIO.getCode());//差量
                            String TR = map.get(ProportionTypeEnum.TASK_RATIO.getCode());//任务量
                            double br = StringUtils.isBlank(BR) ? 0 : Double.parseDouble(BR) / 100;
                            double pr = StringUtils.isBlank(PR) ? 0 : Double.parseDouble(PR) / 100;
                            double dr = StringUtils.isBlank(DR) ? 0 : Double.parseDouble(DR) / 100;
                            double tr = StringUtils.isBlank(TR) ? 0 : Double.parseDouble(TR) / 100;
                            inventoryAllotDetail.getChannelScopes().forEach(channelScope -> {
                                scItemSalePlanSingle.put(channelScope.getChannelId() + ":" + k, 0);
                            });
                            for (Entry<String, Integer> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
//                            String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                double diffPercent = diffMap.get(stringIntegerEntry.getKey()) == null ? 0d: diffMap.get(stringIntegerEntry.getKey());
                                double planPercent = planMap.get(stringIntegerEntry.getKey()) == null ? 0d:planMap.get(stringIntegerEntry.getKey());
                                double budgetPercent = budgetMap.get(stringIntegerEntry.getKey())== null ? 0d:budgetMap.get(stringIntegerEntry.getKey());
                                double taskPercent = taskMap.get(stringIntegerEntry.getKey()) == null ? 0d: taskMap.get(stringIntegerEntry.getKey()) ;
                                //综合占比
                                double wholePercent = diffPercent * dr + planPercent * pr + budgetPercent * br + taskPercent * tr;
                                percentMap.put(stringIntegerEntry.getKey(), new BigDecimal(wholePercent).setScale(4, RoundingMode.DOWN).doubleValue());
                            }
                            log.info("渠道维度-规则值:"+dimensionSDO.getRuleValue()+"||综合占比:" + percentMap);
                        }
                    }

                    //部门
                    if (CollectionUtils.isNotEmpty(inventoryAllotDetail.getDepartmentScopes())) {
                        Map<String, Map<String, List<SalesPlanStatScItemSDO>>> finalDepartmentPlanMap = departmentPlanMap;
                        //差量比例
                        if ("1".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
//
                            //货品所有渠道/所有部门/所有业务员的累计月度计划量
                            Map<String, BigDecimal> scItemTaskTotal = new HashMap<>();
                            //货品+渠道/部门/业务员的月度计划量
                            Map<String, BigDecimal> scItemTaskSingle = new HashMap<>();
                            //Map<String, SalesPlanStatScItemSDO> departmentMap = batchDepartmentGetSalesPlanStatScItemSDO(inventoryAllotDetail, inventoryAllotDetail.getDepartmentScopes(), k);

                            inventoryAllotDetail.getDepartmentScopes().forEach(departmentScope -> {
                                // SalesPlanStatScItemSDO salesPlanStatScItemSDO = departmentGetSalesPlanStatScItemSDO(inventoryAllotDetail, departmentScope, k);

                                Integer taskCount = 0;
                                if (Objects.nonNull(finalDepartmentPlanMap) &&MapUtils.isNotEmpty(finalDepartmentPlanMap.get(k))&&CollectionUtils.isNotEmpty(finalDepartmentPlanMap.get(k).get(departmentScope.getDepartmentId()))) {
                                    taskCount = Objects.isNull(finalDepartmentPlanMap.get(k).get(departmentScope.getDepartmentId()).get(0).getTaskCount()) ? 0 : finalDepartmentPlanMap.get(k).get(departmentScope.getDepartmentId()).get(0).getTaskCount();
                                }
                                //任务量-发货数量    某个渠道的差量 scItemTaskSingle - 总差量 scItemTaskTotal
                                Map<String, BigDecimal> orderDeliveryMap = getDeliveryAmount(k, inventoryAllotDetail.getOrgId(), departmentScope.getDepartmentId(), InventoryAllotTypeEnum.DEPARTMENT,wareHouseIds);
                                BigDecimal taskDelta = new BigDecimal(taskCount).subtract(orderDeliveryMap.get(departmentScope.getDepartmentId() + ":" + k) == null ? BigDecimal.valueOf(0) : orderDeliveryMap.get(departmentScope.getDepartmentId() + ":" + k));
                                if (taskDelta.compareTo(new BigDecimal("0")) < 0) {
                                    taskDelta = new BigDecimal("0");
                                }
                                scItemTaskTotal.put(k, (scItemTaskTotal.get(k) == null ? BigDecimal.valueOf(0).add(taskDelta) : scItemTaskTotal.get(k).add(taskDelta)));
                                scItemTaskSingle.put(departmentScope.getDepartmentId() + ":" + k, taskDelta);

                            });
                            log.info("部门维度-规则值:"+dimensionSDO.getRuleValue()+"||差量:scItemSalePlanSingle:" + JSON.toJSONString(scItemTaskSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemTaskTotal));
                            // todo 差量计算
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemTaskSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemTaskTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemTaskTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent = (stringIntegerEntry.getValue().divide(scItemTaskTotal.get(scItemId),4,BigDecimal.ROUND_DOWN));
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                diffMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }

                        }
                        //计划量占比
                        if ("2".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                            //Map<String, SalesPlanStatScItemSDO> departmentMap = batchDepartmentGetSalesPlanStatScItemSDO(inventoryAllotDetail, inventoryAllotDetail.getDepartmentScopes(), k);

                            inventoryAllotDetail.getDepartmentScopes().forEach(departmentScope -> {
                                // SalesPlanStatScItemSDO salesPlanStatScItemSDO = departmentGetSalesPlanStatScItemSDO(inventoryAllotDetail, departmentScope, k);
                                Integer monthCount = 0;
                                if (Objects.nonNull(finalDepartmentPlanMap) &&MapUtils.isNotEmpty(finalDepartmentPlanMap.get(k))&&CollectionUtils.isNotEmpty(finalDepartmentPlanMap.get(k).get(departmentScope.getDepartmentId()))) {
                                    monthCount = Objects.isNull(finalDepartmentPlanMap.get(k).get(departmentScope.getDepartmentId()).get(0).getMonthCount())?0:finalDepartmentPlanMap.get(k).get(departmentScope.getDepartmentId()).get(0).getMonthCount();
                                }

                                scItemSalePlanTotal.put(k, (scItemSalePlanTotal.get(k) == null ? new BigDecimal(monthCount) : scItemSalePlanTotal.get(k).add (new BigDecimal(monthCount))));
                                scItemSalePlanSingle.put(departmentScope.getDepartmentId() + ":" + k, (new BigDecimal(monthCount)));
                            });
                            log.info("部门维度-规则值:"+dimensionSDO.getRuleValue()+"||计划量:scItemSalePlanSingle:" + JSON.toJSONString(scItemSalePlanSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemSalePlanTotal));
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemSalePlanTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemSalePlanTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent = (stringIntegerEntry.getValue().divide(scItemSalePlanTotal.get(scItemId),4,BigDecimal.ROUND_DOWN));
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                planMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }
                        }

                        //预算占比
                        if ("3".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                            Map<String, Map<String, List<MonthContractAndRollingCountResponse>>> finalScItemContractPlanDepartment = scItemContractPlanDepartment;
                            inventoryAllotDetail.getDepartmentScopes().forEach(departmentScope -> {
                                Integer mont = 0;
                                if (finalScItemContractPlanDepartment != null && MapUtils.isNotEmpty(finalScItemContractPlanDepartment.get(k))&&CollectionUtils.isNotEmpty(finalScItemContractPlanDepartment.get(k).get(departmentScope.getDepartmentId()))) {
                                    MonthContractAndRollingCountResponse monthContractAndRollingCountResponse = finalScItemContractPlanDepartment.get(k).get(departmentScope.getDepartmentId()).get(0);
//                                throw new FacadeException("OTS-06-005-00-15-003");
                                    mont = monthContractAndRollingCountResponse.getMonthContractCount() == null ? 0 : monthContractAndRollingCountResponse.getMonthContractCount();
                                }
                                scItemSalePlanTotal.put(k, (scItemSalePlanTotal.get(k) == null ? new BigDecimal(mont) : scItemSalePlanTotal.get(k).add(new BigDecimal(mont)) ));
                                scItemSalePlanSingle.put(departmentScope.getDepartmentId() + ":" + k, new BigDecimal(mont));
                            });
                            log.info("部门维度-规则值:"+dimensionSDO.getRuleValue()+"||预算:scItemSalePlanSingle:" + JSON.toJSONString(scItemSalePlanSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemSalePlanTotal));
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemSalePlanTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemSalePlanTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent =  (stringIntegerEntry.getValue().divide(scItemSalePlanTotal.get(scItemId),4,BigDecimal.ROUND_DOWN));
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                budgetMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }
                        }
                        //任务量占比
                        if ("4".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                           // Map<String, SalesPlanStatScItemSDO> departmentMap = batchDepartmentGetSalesPlanStatScItemSDO(inventoryAllotDetail, inventoryAllotDetail.getDepartmentScopes(), k);
                            inventoryAllotDetail.getDepartmentScopes().forEach(departmentScope -> {
                                // SalesPlanStatScItemSDO salesPlanStatScItemSDO = departmentGetSalesPlanStatScItemSDO(inventoryAllotDetail, departmentScope, k);
                                Integer taskCount = 0;
                                if (Objects.nonNull(finalDepartmentPlanMap) &&MapUtils.isNotEmpty(finalDepartmentPlanMap.get(k))&&CollectionUtils.isNotEmpty(finalDepartmentPlanMap.get(k).get(departmentScope.getDepartmentId()))) {
                                    taskCount = Objects.isNull(finalDepartmentPlanMap.get(k).get(departmentScope.getDepartmentId()).get(0).getTaskCount())?0:finalDepartmentPlanMap.get(k).get(departmentScope.getDepartmentId()).get(0).getTaskCount();
                                }
                                scItemSalePlanTotal.put(k, (scItemSalePlanTotal.get(k) == null ? new BigDecimal(taskCount) : scItemSalePlanTotal.get(k).add (new BigDecimal(taskCount))));
                                scItemSalePlanSingle.put(departmentScope.getDepartmentId() + ":" + k, new BigDecimal(taskCount));
                            });
                            log.info("部门维度-规则值:"+dimensionSDO.getRuleValue()+"||任务量:scItemSalePlanSingle:" + JSON.toJSONString(scItemSalePlanSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemSalePlanTotal));
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemSalePlanTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemSalePlanTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent =  (stringIntegerEntry.getValue().divide(scItemSalePlanTotal.get(scItemId),4,BigDecimal.ROUND_DOWN));
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                taskMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }
                        }
                        //综合占比
                        if ("5".equals(dimensionSDO.getRuleValue())) {
                            Map<String, Integer> scItemSalePlanTotal = new HashMap<>();
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                            Map<String, String> map = JSONObject.parseObject(dimensionSDO.getDetails(), Map.class);
                            String BR = map.get(ProportionTypeEnum.BUDGET_RATIO.getCode());//预算
                            String PR = map.get(ProportionTypeEnum.PLAN_RATIO.getCode());//计划量
                            String DR = map.get(ProportionTypeEnum.DIFFERENCE_RATIO.getCode());//差量
                            String TR = map.get(ProportionTypeEnum.TASK_RATIO.getCode());//任务量
                            double br = StringUtils.isBlank(BR) ? 0 : Double.parseDouble(BR) / 100;
                            double pr = StringUtils.isBlank(PR) ? 0 : Double.parseDouble(PR) / 100;
                            double dr = StringUtils.isBlank(DR) ? 0 : Double.parseDouble(DR) / 100;
                            double tr = StringUtils.isBlank(TR) ? 0 : Double.parseDouble(TR) / 100;

                            inventoryAllotDetail.getDepartmentScopes().forEach(departmentScope -> {
                                scItemSalePlanSingle.put(departmentScope.getDepartmentId() + ":" + k, new BigDecimal(0));
                            });

                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
//                            String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                double diffPercent = diffMap.get(stringIntegerEntry.getKey()) == null ? 0d: diffMap.get(stringIntegerEntry.getKey());
                                double planPercent = planMap.get(stringIntegerEntry.getKey()) == null ? 0d:planMap.get(stringIntegerEntry.getKey());
                                double budgetPercent = budgetMap.get(stringIntegerEntry.getKey())== null ? 0d:budgetMap.get(stringIntegerEntry.getKey());
                                double taskPercent = taskMap.get(stringIntegerEntry.getKey()) == null ? 0d: taskMap.get(stringIntegerEntry.getKey()) ;
                                //综合占比
                                double wholePercent = diffPercent * dr + planPercent * pr + budgetPercent * br + taskPercent * tr;
                                percentMap.put(stringIntegerEntry.getKey(), new BigDecimal(wholePercent).setScale(4, RoundingMode.DOWN).doubleValue());
                            }
                            log.info("部门维度-规则值:"+dimensionSDO.getRuleValue()+"||综合占比:" + percentMap);
                        }

                    }

                    //业务员
                    if (CollectionUtils.isNotEmpty(inventoryAllotDetail.getSalesmanScopes())) {
                        Map<String, Map<String, List<SalesPlanStatScItemSDO>>> finalSalesmenPlanMap = salesmenPlanMap;
                        //差量比例
                        if ("1".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {

                            //货品所有渠道/所有部门/所有业务员的累计月度计划量
                            Map<String, BigDecimal> scItemTaskTotal = new HashMap<>();
                            //货品+渠道/部门/业务员的月度计划量
                            Map<String, BigDecimal> scItemTaskSingle = new HashMap<>();
                           // Map<String, SalesPlanStatScItemSDO> salesmenMap = batchSalesmanGetSalesPlanStatScItemSDO(inventoryAllotDetail, inventoryAllotDetail.getSalesmanScopes(), k);


                            inventoryAllotDetail.getSalesmanScopes().forEach(salesmanScope -> {
                                //SalesPlanStatScItemSDO salesPlanStatScItemSDO = salesmanGetSalesPlanStatScItemSDO(inventoryAllotDetail, salesmanScope, k);
                                Integer taskCount = 0;
                                if (Objects.nonNull(finalSalesmenPlanMap)&&Objects.nonNull(finalSalesmenPlanMap.get(k))&&CollectionUtils.isNotEmpty(finalSalesmenPlanMap.get(k).get(salesmanScope.getSalesmanId()))) {
                                    taskCount =Objects.isNull(finalSalesmenPlanMap.get(k).get(salesmanScope.getSalesmanId()).get(0).getTaskCount()) ? 0 : finalSalesmenPlanMap.get(k).get(salesmanScope.getSalesmanId()).get(0).getTaskCount();
                                }
                                //任务量-发货数量    某个渠道的差量 scItemTaskSingle - 总差量 scItemTaskTotal
                                Map<String, BigDecimal> orderDeliveryMap = getDeliveryAmount(k, inventoryAllotDetail.getOrgId(), salesmanScope.getSalesmanId(), InventoryAllotTypeEnum.SALESMAN,wareHouseIds);
                                BigDecimal taskDelta = new BigDecimal(taskCount).subtract(orderDeliveryMap.get(salesmanScope.getSalesmanId() + ":" + k) == null ? BigDecimal.valueOf(0) : orderDeliveryMap.get(salesmanScope.getSalesmanId() + ":" + k));
                                if (taskDelta.compareTo(new BigDecimal("0")) < 0) {
                                    taskDelta = new BigDecimal("0");
                                }
                                scItemTaskTotal.put(k, (scItemTaskTotal.get(k) == null ? taskDelta : scItemTaskTotal.get(k).add(taskDelta)));
                                scItemTaskSingle.put(salesmanScope.getSalesmanId() + ":" + k, taskDelta);

                            });
                            log.info("业务员维度-规则值:"+dimensionSDO.getRuleValue()+"||差量:scItemTaskSingle:" + JSON.toJSONString(scItemTaskSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemTaskTotal));
                            // 差量计算
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemTaskSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemTaskTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemTaskTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent = stringIntegerEntry.getValue().divide(scItemTaskTotal.get(scItemId), 4, BigDecimal.ROUND_DOWN);
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                diffMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }

                        }
                        //计划量占比
                        if ("2".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                            //Map<String, SalesPlanStatScItemSDO> salesmenMap = batchSalesmanGetSalesPlanStatScItemSDO(inventoryAllotDetail, inventoryAllotDetail.getSalesmanScopes(), k);

                            inventoryAllotDetail.getSalesmanScopes().forEach(salesmanScope -> {
                                //SalesPlanStatScItemSDO salesPlanStatScItemSDO = salesmanGetSalesPlanStatScItemSDO(inventoryAllotDetail, salesmanScope, k);
                                int count = 0;
                    if (Objects.nonNull(finalSalesmenPlanMap)&&Objects.nonNull(finalSalesmenPlanMap.get(k))&&CollectionUtils.isNotEmpty(finalSalesmenPlanMap.get(k).get(salesmanScope.getSalesmanId()))) {
                                    count =Objects.isNull(finalSalesmenPlanMap.get(k).get(salesmanScope.getSalesmanId()).get(0).getMonthCount()) ? 0 : finalSalesmenPlanMap.get(k).get(salesmanScope.getSalesmanId()).get(0).getMonthCount();
                                }
                                scItemSalePlanTotal.put(k, (scItemSalePlanTotal.get(k) == null ? new BigDecimal(count) : scItemSalePlanTotal.get(k).add(new BigDecimal(count)) ));
                                scItemSalePlanSingle.put(salesmanScope.getSalesmanId() + ":" + k, new BigDecimal(count));
                            });
                            log.info("业务员维度-规则值:"+dimensionSDO.getRuleValue()+"||计划量:scItemSalePlanSingle:" + JSON.toJSONString(scItemSalePlanSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemSalePlanTotal));
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemSalePlanTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemSalePlanTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent =  (stringIntegerEntry.getValue().divide( scItemSalePlanTotal.get(scItemId),4,BigDecimal.ROUND_DOWN));
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                planMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }
                        }

                        //预算占比
                        if ("3".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();

                            Map<String, Map<String, List<MonthContractAndRollingCountResponse>>> finalScItemContractPlanSalesmen = scItemContractPlanSalesmen;
                            inventoryAllotDetail.getSalesmanScopes().forEach(salesmanScope -> {
                                int mont = 0;
                                if (MapUtils.isNotEmpty(finalScItemContractPlanSalesmen) && MapUtils.isNotEmpty(finalScItemContractPlanSalesmen.get(k))&&CollectionUtils.isNotEmpty(finalScItemContractPlanSalesmen.get(k).get(salesmanScope.getSalesmanId()))) {
                                    MonthContractAndRollingCountResponse monthContractAndRollingCountResponse = finalScItemContractPlanSalesmen.get(k).get(salesmanScope.getSalesmanId()).get(0);
//                                throw new FacadeException("OTS-06-005-00-15-003");
                                    mont = monthContractAndRollingCountResponse.getMonthContractCount() == null ? 0 : monthContractAndRollingCountResponse.getMonthContractCount();
                                }
                                scItemSalePlanTotal.put(k, (scItemSalePlanTotal.get(k) == null ? new BigDecimal(mont) : scItemSalePlanTotal.get(k).add(new BigDecimal(mont) )));
                                scItemSalePlanSingle.put(salesmanScope.getSalesmanId() + ":" + k, new BigDecimal(mont) );
                            });
                            log.info("业务员维度-规则值:"+dimensionSDO.getRuleValue()+"||预算:scItemSalePlanSingle:" + JSON.toJSONString(scItemSalePlanSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemSalePlanTotal));
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemSalePlanTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemSalePlanTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent = (stringIntegerEntry.getValue().divide( scItemSalePlanTotal.get(scItemId),4,BigDecimal.ROUND_DOWN));
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                budgetMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }
                        }
                        //任务量占比
                        if ("4".equals(dimensionSDO.getRuleValue()) || "5".equals(dimensionSDO.getRuleValue())) {
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                            //Map<String, SalesPlanStatScItemSDO> salesmenMap = batchSalesmanGetSalesPlanStatScItemSDO(inventoryAllotDetail, inventoryAllotDetail.getSalesmanScopes(), k);

                            inventoryAllotDetail.getSalesmanScopes().forEach(salesmanScope -> {
                                //SalesPlanStatScItemSDO salesPlanStatScItemSDO = salesmanGetSalesPlanStatScItemSDO(inventoryAllotDetail, salesmanScope, k);
                                Integer taskCount = 0;
                                if (Objects.nonNull(finalSalesmenPlanMap)&&Objects.nonNull(finalSalesmenPlanMap.get(k))&&CollectionUtils.isNotEmpty(finalSalesmenPlanMap.get(k).get(salesmanScope.getSalesmanId()))) {
                                    taskCount = Objects.isNull(finalSalesmenPlanMap.get(k).get(salesmanScope.getSalesmanId()).get(0).getTaskCount())?0:finalSalesmenPlanMap.get(k).get(salesmanScope.getSalesmanId()).get(0).getTaskCount();
                                }
                                scItemSalePlanTotal.put(k, (scItemSalePlanTotal.get(k) == null ? new BigDecimal(taskCount) : scItemSalePlanTotal.get(k).add(new BigDecimal(taskCount))) );
                                scItemSalePlanSingle.put(salesmanScope.getSalesmanId() + ":" + k, new BigDecimal(taskCount));
                            });
                            log.info("业务员维度-规则值:"+dimensionSDO.getRuleValue()+"||任务量:scItemSalePlanSingle:" + JSON.toJSONString(scItemSalePlanSingle) + "||scItemTaskTotal:" + JSON.toJSONString(scItemSalePlanTotal));
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
                                String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                BigDecimal total = scItemSalePlanTotal.get(scItemId);
                                if (total.intValue() == 0){
                                    scItemSalePlanTotal.put(scItemId,new BigDecimal("1"));
                                }
                                BigDecimal planPercent = (stringIntegerEntry.getValue().divide(scItemSalePlanTotal.get(scItemId),4,BigDecimal.ROUND_DOWN));
                                percentMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                                taskMap.put(stringIntegerEntry.getKey(), planPercent.doubleValue());
                            }
                        }
                        //综合占比
                        if ("5".equals(dimensionSDO.getRuleValue())) {
                            Map<String, BigDecimal> scItemSalePlanTotal = new HashMap<>();
                            Map<String, BigDecimal> scItemSalePlanSingle = new HashMap<>();
                            Map<String, String> map = JSONObject.parseObject(dimensionSDO.getDetails(), Map.class);
                            String BR = map.get(ProportionTypeEnum.BUDGET_RATIO.getCode());//预算
                            String PR = map.get(ProportionTypeEnum.PLAN_RATIO.getCode());//计划量
                            String DR = map.get(ProportionTypeEnum.DIFFERENCE_RATIO.getCode());//差量
                            String TR = map.get(ProportionTypeEnum.TASK_RATIO.getCode());//任务量
                            double br = StringUtils.isBlank(BR) ? 0 : Double.parseDouble(BR) / 100;
                            double pr = StringUtils.isBlank(PR) ? 0 : Double.parseDouble(PR) / 100;
                            double dr = StringUtils.isBlank(DR) ? 0 : Double.parseDouble(DR) / 100;
                            double tr = StringUtils.isBlank(TR) ? 0 : Double.parseDouble(TR) / 100;

                            inventoryAllotDetail.getSalesmanScopes().forEach(salesmanScope -> {
                                scItemSalePlanSingle.put(salesmanScope.getSalesmanId() + ":" + k, new BigDecimal(0));
                            });
                            for (Entry<String, BigDecimal> stringIntegerEntry : scItemSalePlanSingle.entrySet()) {
//                            String scItemId = stringIntegerEntry.getKey().split(":")[1];
                                double diffPercent = diffMap.get(stringIntegerEntry.getKey()) == null ? 0d: diffMap.get(stringIntegerEntry.getKey());
                                double planPercent = planMap.get(stringIntegerEntry.getKey()) == null ? 0d:planMap.get(stringIntegerEntry.getKey());
                                double budgetPercent = budgetMap.get(stringIntegerEntry.getKey())== null ? 0d:budgetMap.get(stringIntegerEntry.getKey());
                                double taskPercent = taskMap.get(stringIntegerEntry.getKey()) == null ? 0d: taskMap.get(stringIntegerEntry.getKey()) ;
                                //综合占比
                                double wholePercent = diffPercent * dr + planPercent * pr + budgetPercent * br + taskPercent * tr;
                                percentMap.put(stringIntegerEntry.getKey(), new BigDecimal(wholePercent).setScale(4, RoundingMode.DOWN).doubleValue());
                            }
                            log.info("业务员维度-规则值:"+dimensionSDO.getRuleValue()+"||综合占比:" + percentMap);
                        }

                    }

                    log.info("分配计算的比例差量：" + JSON.toJSONString(diffMap));
                    log.info("分配计算的比例计划：" + JSON.toJSONString(planMap));
                    log.info("分配计算的比例任务量：" + JSON.toJSONString(taskMap));
                    log.info("分配计算的比例预算：" + JSON.toJSONString(budgetMap));
                    log.info("最终分配计算的比例：" + JSON.toJSONString(percentMap));
                    //库存*比例

                    Long remainInventoryQty;
                    List<InventoryAllotLineSDO> tempDiffList=new ArrayList<>();


                    long startClac=System.currentTimeMillis();
                    //如果是分解策略是渠道配置
                    if (CollectionUtils.isNotEmpty(inventoryAllotDetail.getChannelScopes())) {
                        inventoryAllotDetail.getChannelScopes().forEach(channelScope -> {
                            InventoryAllotLineSDO inventoryAllotLineSDO = buildInventoryAllotLineSDO(entryInventory, percent, channelScope.getChannelId(), channelScope.getChannelName()
                                    , percentMap,inventoryAllotDetail.getFeatures(),scItemSDOMap.get(k));
                            log.info("渠道:"+channelScope.getChannelName()+"-id:"+channelScope.getChannelId()+"-库存分解明细:"+JSONObject.toJSONString(inventoryAllotLineSDO));
                            if (inventoryAllotLineSDO != null) {
                                //inventoryAllotLineSDOS.add(inventoryAllotLineSDO);
                                tempDiffList.add(inventoryAllotLineSDO);
                            }
                        });
                    }
                    //部门
                    if (CollectionUtils.isNotEmpty(inventoryAllotDetail.getDepartmentScopes())) {

                        inventoryAllotDetail.getDepartmentScopes().forEach(departmentScope -> {
                            InventoryAllotLineSDO inventoryAllotLineSDO = buildInventoryAllotLineSDO(entryInventory, percent, departmentScope.getDepartmentId(), departmentScope.getDepartmentName()
                                    , percentMap, inventoryAllotDetail.getFeatures(),scItemSDOMap.get(k));
                            log.info("部门:"+departmentScope.getDepartmentName()+"-id:"+departmentScope.getDepartmentId()+"-库存分解明细:"+JSONObject.toJSONString(inventoryAllotLineSDO));
                            if (inventoryAllotLineSDO != null) {
                                // inventoryAllotLineSDOS.add(inventoryAllotLineSDO);
                                tempDiffList.add(inventoryAllotLineSDO);
                            }
                        });
                    }
                    //业务员
                    if (CollectionUtils.isNotEmpty(inventoryAllotDetail.getSalesmanScopes())) {
                        inventoryAllotDetail.getSalesmanScopes().forEach(salesmanScope -> {
                            InventoryAllotLineSDO inventoryAllotLineSDO = buildInventoryAllotLineSDO(entryInventory, percent, salesmanScope.getSalesmanId(), salesmanScope.getSalesmanName()
                                    , percentMap,inventoryAllotDetail.getFeatures(),scItemSDOMap.get(k));
                            log.info("业务员:"+salesmanScope.getSalesmanName()+"-id:"+salesmanScope.getSalesmanId()+"-库存分解明细:"+JSONObject.toJSONString(inventoryAllotLineSDO));
                            if (inventoryAllotLineSDO != null) {
                                //inventoryAllotLineSDOS.add(inventoryAllotLineSDO);
                                tempDiffList.add(inventoryAllotLineSDO);
                            }
                        });
                    }

                    log.info("每日库存分解计算耗时:"+(System.currentTimeMillis()-startClac));
                    //将剩余库存全给第一个元素


                    long occupyQty = tempDiffList.stream().mapToLong(o -> null != o.getDistributionQuantity() ? new BigDecimal(o.getDistributionQuantity()).longValue() : new BigDecimal(0).longValue()).sum();
                    remainInventoryQty = percent.multiply(entryInventory.getValue()).longValue()-occupyQty;

                    if (occupyQty>0&&remainInventoryQty>0&&CollectionUtils.isNotEmpty(tempDiffList)){
                        List<InventoryAllotLineSDO> collect = tempDiffList.stream().filter(o -> new BigDecimal(o.getDistributionQuantity()).compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                        InventoryAllotLineSDO inventoryAllotLineSDO = collect.get(0);
                        long disQty = Long.parseLong(inventoryAllotLineSDO.getDistributionQuantity());
                        long totalDisQty=disQty+remainInventoryQty;
                        inventoryAllotLineSDO.setDistributionQuantity(String.valueOf(totalDisQty));
                        inventoryAllotLineSDO.setRemainingQuantity(String.valueOf(totalDisQty));

                    }

                    inventoryAllotLineSDOS.addAll(tempDiffList);

                    inventoryAllotSDO.setInventoryAllotLineSDOS(inventoryAllotLineSDOS);
                    long startTime6=System.currentTimeMillis();
                    log.info("每日库存分解一次分配耗时:"+(startTime6-startTime5));
                }
                InventoryAllotEntity inventoryAllotEntity = InventoryAllotFactory.createInventoryAllot(inventoryAllotSDO);
                //inventoryAllotEntity.create();
                SpringContextUtil.getBean(InventoryAllotServiceImpl.class).createInventoryAllot(inventoryAllotEntity);
            }
            log.info("每日库存分解结束,耗时:" + (System.currentTimeMillis() - startTime));
        } catch (Exception e) {
            log.error("库存分解-异常",e);
            return Result.fail("OTS-06-005-00-15-000",e.getMessage());
        }
        return Result.success(true);
    }

    private Map<String, Map<String, List<MonthContractAndRollingCountResponse>>> getScItemContractPlan(ContractStatDimensionEnum type,List<String> scItems, List<String> saleChannelList) {
        QueryQuantityListByAddressAndScItemRequest queryRequest = new QueryQuantityListByAddressAndScItemRequest();
        queryRequest.setType(type.getCode());
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        queryRequest.setContractYear(year + "");
        queryRequest.setPlanMonth(month + "");
        switch (type){
            case SALES_CHANNEL_SC_ITEM:
                queryRequest.setOrgSalesChannelCodes(saleChannelList);
                break;
            case DEPARTMENT_SC_ITEM:
                queryRequest.setOrgSalesDepartmentCodes(saleChannelList);
                break;
            case EMPLOYEE_SC_ITEM:
                queryRequest.setManageEmployeeIds(saleChannelList);
                break;
        }

        queryRequest.setScItemIds(scItems);
        QueryQuantityListByAddressAndScItemResponse response = salesPlanService.queryQuantityListByAddressAndScItem(queryRequest);
        if (Objects.isNull(response)||CollectionUtils.isEmpty(response.getResult())){
            return null;
        }
        Map<String, Map<String, List<MonthContractAndRollingCountResponse>>> channelMapMap=new HashMap<>();
        Map<String, List<MonthContractAndRollingCountResponse>> collect = response.getResult().stream().collect(Collectors.groupingBy(MonthContractAndRollingCountResponse::getScItemId));
        for (Entry<String, List<MonthContractAndRollingCountResponse>> entry : collect.entrySet()) {
            if (CollectionUtils.isNotEmpty(entry.getValue())){
                Map<String, List<MonthContractAndRollingCountResponse>> channelGroupMap;
                switch (type){
                    case SALES_CHANNEL_SC_ITEM:
                        channelGroupMap = entry.getValue().stream().collect(Collectors.groupingBy(MonthContractAndRollingCountResponse::getOrgSalesChannelCode));
                        break;
                    case DEPARTMENT_SC_ITEM:
                        channelGroupMap = entry.getValue().stream().collect(Collectors.groupingBy(MonthContractAndRollingCountResponse::getOrgSalesDepartmentCode));
                        break;
                    case EMPLOYEE_SC_ITEM:
                        channelGroupMap = entry.getValue().stream().collect(Collectors.groupingBy(MonthContractAndRollingCountResponse::getManageEmployeeId));
                        break;
                    default:
                        throw new IllegalStateException("Unexpected value: " + type);
                }

                channelMapMap.put(entry.getKey(),channelGroupMap) ;
            }
        }
        return channelMapMap;
    }

    // 增加本地事务能力
    @EpochTransactional(appCode="cr_platform_enhance", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void createInventoryAllot(InventoryAllotEntity inventoryAllotEntity) {
        inventoryAllotEntity.create();
    }

    /**
     * 构建分解明细sdo
     *
     * @param entryInventory
     * @param percent
     * @param dimensionId
     * @param dimensionName
     * @param percentMap
     * @return
     */
    private InventoryAllotLineSDO buildInventoryAllotLineSDO(Entry<String, BigDecimal> entryInventory, BigDecimal percent,
                                                             String dimensionId, String dimensionName,
                                                             Map<String, Double> percentMap, Map<String, String> features, ScItemSDO scItemSDO) {
        //分配
        String itemId = entryInventory.getKey();
        BigDecimal entryInventoryValue = entryInventory.getValue();

        InventoryAllotLineSDO inventoryAllotLineSDO = new InventoryAllotLineSDO();
        //查询货品名称和库存单位
//        SearchScItemRequest scItemRequest = new SearchScItemRequest();
//        Map<String, List<String>> map = new HashMap<>();
//        List<String> scItemIds = new ArrayList<>();
//        scItemIds.add(itemId);
//        map.put("scItemIds", scItemIds);
//        scItemRequest.setSearchReqDTO(map);
//        log.info("库存分解-查询货品信息请求：" + JSON.toJSONString(scItemRequest));
//        Result<List<ScItemSDO>> listResult = baseDataService.searchScItem(scItemRequest);
//        log.info("库存分解-查询货品信息响应：" + JSON.toJSONString(listResult));
//        if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())) {
////            throw new FacadeException("OTS-06-005-00-15-005",itemId);
//            log.error("库存分解-执行比例计算时货品未查到：" + JSON.toJSONString(listResult));
//            return null;
//
//        }
       // ScItemSDO scItemSDO = listResult.getResult().get(0);
        if (Objects.isNull(scItemSDO)){
            log.error("库存分解-执行比例计算时货品未查到：" + itemId);
         return null;
        }
        inventoryAllotLineSDO.setScItemId(itemId);
        inventoryAllotLineSDO.setScItemName(scItemSDO.getTitle());
        inventoryAllotLineSDO.setInventoryUnit(scItemSDO.getUnit());
        //可用库存
        BigDecimal availableInventory = entryInventoryValue.setScale(0, BigDecimal.ROUND_DOWN);
        inventoryAllotLineSDO.setAvailableInventory(availableInventory.toString());
        inventoryAllotLineSDO.setDimensionId(dimensionId);
        inventoryAllotLineSDO.setDimensionName(dimensionName);
        //计算比例
        Double finalPercent = percentMap.get(dimensionId + ":" + itemId);
        if (finalPercent == null || finalPercent.isNaN() || finalPercent < 0) {
            finalPercent = 0.0;
        }
        BigDecimal tmp = new BigDecimal(finalPercent);
        finalPercent = tmp.setScale(4, RoundingMode.DOWN).doubleValue();
        //因为出现数据丢失问题，导致出现浮点数，结合业务需求百分比保留2位小数，使用 finalPercent*10000 / 100
        Integer finalValue = ((Double)(finalPercent*10000)).intValue();
        Double per = (finalValue * 1.0)/100;
        inventoryAllotLineSDO.setCalculationScale(String.valueOf(per) + "%");
        //分配数量
        BigDecimal multiply = availableInventory.multiply(percent).multiply(new BigDecimal(finalPercent));
        String distributionQuantity = multiply.setScale(0, RoundingMode.DOWN).toString();
        inventoryAllotLineSDO.setDistributionQuantity(distributionQuantity);
        inventoryAllotLineSDO.setRemainingQuantity(distributionQuantity);
        Map<String, String> feature = new HashMap<>();
        feature.put("sc_item_outer_id",scItemSDO.getOuterId());
        feature.put("dimension_out_id", features.get(dimensionId));
        inventoryAllotLineSDO.setFeatures(JSONObject.toJSONString(feature));
        return inventoryAllotLineSDO;
//        inventoryAllotLineSDOS.add(inventoryAllotLineSDO);
    }

    // 手动导入分解数量
    public Map<String, String> manualAllotReduceQuantity(InventoryAllotDetail inventoryAllotDetail) {
        QueryManualAllotRequest request = new QueryManualAllotRequest();
        request.setOrganizationCode(inventoryAllotDetail.getOrgId());
        QueryDuctManualAllotResponse response = inventoryAllotRepository.queryManualImportAllot(request);
        if (Objects.isNull(response) || MapUtils.isEmpty(response.getManualDuctMap())) {
            return Maps.newHashMap();
        }
        return response.getManualDuctMap();
    }

    @Override
    public Result<List<InventoryAllotLineDTO>> importAdjustedAllotLineData(ImportAdjustedAllotLineDataRequest request) {

        List<InventoryAllotLineDTO> inventoryAllotLineDTOList = request.getRequestList();
        List<InventoryAllotLineDTO> inventoryAllotResultList = Lists.newArrayList();
        if (CollectionUtils.isEmpty(inventoryAllotLineDTOList)) {
            return Result.listEmptySuccess();
        }

        //基本检查
        checkRequest(inventoryAllotLineDTOList, inventoryAllotResultList);

        //丰富信息
        enrichInventoryAllotLineDTOList(inventoryAllotLineDTOList);

        //去重获取到外部货品编码列表
        List<String> scItemIds = inventoryAllotLineDTOList.stream().map(InventoryAllotLineDTO::getScItemId).distinct().collect(Collectors.toList());

        //获取到外部Id和商品的映射关系
        Map<String, ScItemSDO> scItemMap = getScItemMap(scItemIds);

        //根据orgCode获取销售组织信息
        Map<String, OrganizationSDO> salesOrganizationInfoMap = getOrganizationInfoMap(inventoryAllotLineDTOList, SALES_ORG_CODE_TYPE);

        //根据DimensionCode获取部门
        Map<String, OrganizationSDO> organizationInfoMap = getOrganizationInfoMap(inventoryAllotLineDTOList, DEPARTMENT_CODE_TYPE);

        //根据DimensionCode获取业务员组织信息
        Map<String, EmployeeSDO> salesmanMap = getSalesmanMap(inventoryAllotLineDTOList);

        //baselineGetEmployeeByIdsAll
        //根据DimensionCode获取业务渠道信息
        Map<String, ChannelSDO> channelInfoMap = getBusinessChannelInfoMap(inventoryAllotLineDTOList);

        //获取手工导单列表，单号以M开头，结果写入distributionId
        List<Integer> indexList=new ArrayList<>();
        int size =inventoryAllotLineDTOList.size();
        for(int i=0;i<size;i++){
            if(inventoryAllotLineDTOList.get(i).getDistributionId()!=null
                &&!inventoryAllotLineDTOList.get(i).getDistributionId().startsWith(MANUAL_IMPORT_FLAG)){
                indexList.add(i);
            }
        }
        List<InventoryAllotLineDTO> manualInventoryAllotLineDTOS =
                inventoryAllotLineDTOList.stream().filter(line -> StringUtils.isNotBlank(line.getDistributionId())).collect(Collectors.toList());

        if(CollectionUtils.isNotEmpty(manualInventoryAllotLineDTOS)) {
            //手工单根据分配单ID分组
            Map<String, List<InventoryAllotLineDTO>> manualGroupInventoryAllotLineMap =
                    manualInventoryAllotLineDTOS.stream().collect(Collectors.groupingBy(InventoryAllotLineDTO::getDistributionId));

            for (Entry<String, List<InventoryAllotLineDTO>> manualDistributionEntry:manualGroupInventoryAllotLineMap.entrySet()) {

                //按照group为单位，by明细行检查
                List<InventoryAllotLineDTO> inventoryAllotLineGroup = manualDistributionEntry.getValue();

                Result<Boolean> groupValidateResult = validateInventoryAllotGroup(inventoryAllotLineGroup,
                    salesOrganizationInfoMap, channelInfoMap, organizationInfoMap,salesmanMap,scItemMap);

                //一行失败，整个组失败
                if (!groupValidateResult.isSuccess()) {
                    for (InventoryAllotLineDTO inputInventoryAllotLineDTO : manualDistributionEntry.getValue()) {
                        inputInventoryAllotLineDTO.setErrorMessage(groupValidateResult.getMessage());
                        inventoryAllotResultList.add(inputInventoryAllotLineDTO);
                    }
                }else {
                    InventoryAllotSDO inventoryAllotSDO = buildInventoryAllotSDO(scItemMap,salesOrganizationInfoMap, channelInfoMap, organizationInfoMap ,salesmanMap,manualDistributionEntry);
                    InventoryAllotEntity inventoryAllotEntity = InventoryAllotFactory.createInventoryAllot(inventoryAllotSDO);
                    inventoryAllotEntity.createInventoryAllotModel();
                    //成功一个批次，就在resultList增加该批次的所有DTO
                    inventoryAllotResultList.addAll(manualDistributionEntry.getValue());
                }
                inventoryAllotResultList = inventoryAllotResultList.stream().sorted(Comparator.comparing(InventoryAllotLineDTO::getIndex)).collect(Collectors.toList());
            }
            return Result.success(inventoryAllotResultList);
        }

        //调整明细，ID不为空
        List<InventoryAllotLineDTO> adjustInventoryAllotLineDTOS =
                inventoryAllotLineDTOList.stream().filter(line -> StringUtils.isNotBlank(line.getId())).collect(Collectors.toList());

        Map<String, List<InventoryAllotLineDTO>> groupByAllotId = Nullable.stream(adjustInventoryAllotLineDTOS).collect(Collectors.groupingBy(InventoryAllotLineDTO::getId));

        //分配单分组查询是否限量
        Map<String,Boolean> limitMap=new HashMap<>();
        for (Entry<String, List<InventoryAllotLineDTO>> entry:groupByAllotId.entrySet()){
            if (CollectionUtils.isEmpty(entry.getValue())){
                continue;
            }
            List<InventoryAllotLineDTO> limitList =entry.getValue().stream().filter(o->StringUtils.isNotBlank(o.getLimitSwitch())&&"Y".equalsIgnoreCase(o.getLimitSwitch())).collect(Collectors.toList());
            limitMap.put(entry.getKey(),CollectionUtils.isNotEmpty(limitList));

        }
        //缓存分配单ID
        Map<String,Boolean> inventoryAllotIdMap=Maps.newHashMap();

        //By Row 逐条执行
        for (InventoryAllotLineDTO inputInventoryAllotLineDTO : adjustInventoryAllotLineDTOS) {

            Result<String> validateResult = validateInventoryAllotLine(inputInventoryAllotLineDTO, true,
                    salesOrganizationInfoMap, channelInfoMap,organizationInfoMap,salesmanMap, scItemMap);
            if (!validateResult.isSuccess()) {
                inputInventoryAllotLineDTO.setErrorMessage(validateResult.getMessage());
                inventoryAllotResultList.add(inputInventoryAllotLineDTO);
                continue;
            }
            if (StringUtils.isNotBlank(inputInventoryAllotLineDTO.getDistributionId()) &&
                !inputInventoryAllotLineDTO.getDistributionId().startsWith(MANUAL_IMPORT_FLAG)) {
                appendErrorMessage(inputInventoryAllotLineDTO,"分配单标识号需按照M开头");
                inventoryAllotResultList.add(inputInventoryAllotLineDTO);
            }
            //调整场景
            if (StringUtils.isNotBlank(inputInventoryAllotLineDTO.getId())) {
                boolean isInventoryAllotIdExist= isInventoryAllotIdExist(inventoryAllotIdMap,
                        inputInventoryAllotLineDTO.getId(),limitMap.getOrDefault(inputInventoryAllotLineDTO.getId(),false));
                if(!isInventoryAllotIdExist) {
                    appendErrorMessage(inputInventoryAllotLineDTO,"分配单id找不到");
                }else {
                    inventoryAllotIdMap.put( inputInventoryAllotLineDTO.getId(),Boolean.TRUE);
                    //调整分配数量
                    boolean adjustSuccess= adjustInventoryAllotDistributionQty(inputInventoryAllotLineDTO, scItemMap, channelInfoMap,organizationInfoMap);
                    if (!adjustSuccess) {
                        appendErrorMessage(inputInventoryAllotLineDTO, "明细更新失败，请检查数据");
                    }
                }
                inventoryAllotResultList.add(inputInventoryAllotLineDTO);
            }
        }
        inventoryAllotResultList = inventoryAllotResultList.stream().sorted(Comparator.comparing(InventoryAllotLineDTO::getIndex)).collect(Collectors.toList());
        return Result.success(inventoryAllotResultList);

    }


    private void appendErrorMessage(InventoryAllotLineDTO inputInventoryAllotLineDTO,String errorMessage) {
        if (StringUtils.isBlank(inputInventoryAllotLineDTO.getErrorMessage())) {
            inputInventoryAllotLineDTO.setErrorMessage(errorMessage);
        } else {
            String errorMsg = inputInventoryAllotLineDTO.getErrorMessage() + ";" + errorMessage;
            inputInventoryAllotLineDTO.setErrorMessage(errorMsg);
        }
    }

    private void checkRequest(List<InventoryAllotLineDTO> inventoryAllotLineDTOList,
                              List<InventoryAllotLineDTO> inventoryAllotResultList) {
        for (InventoryAllotLineDTO inventoryAllotLineDTO : inventoryAllotLineDTOList) {
            if (StringUtils.isBlank(inventoryAllotLineDTO.getDistributionId()) && StringUtils.isBlank(
                    inventoryAllotLineDTO.getId())) {
                inventoryAllotLineDTO.setErrorMessage("分配单id和分配单标识号都为空");
                inventoryAllotResultList.add(inventoryAllotLineDTO);
            }
        }
    }

    @NotNull
    private InventoryAllotSDO buildInventoryAllotSDO(Map<String, ScItemSDO> scItemMap,
                                                   Map<String, OrganizationSDO> salesOrganizationInfoMap,
                                                   Map<String, ChannelSDO> channelInfoMap,
                                                   Map<String, OrganizationSDO>  organizationInfoMap,
                                                   Map<String, EmployeeSDO> salesmanMap,
                                                   Entry<String, List<InventoryAllotLineDTO>> manualDistributionEntry) {
        String manualDistributionId = manualDistributionEntry.getKey();
        List<InventoryAllotLineDTO> inventoryAllotLineGroup = manualDistributionEntry.getValue();
        //这里假设了同一个分配单ID的主单字段都相同
        List<InventoryAllotLineDTO> limitList = Nullable.stream(inventoryAllotLineGroup).filter(o->StringUtils.isNotBlank(o.getLimitSwitch())&&"Y".equalsIgnoreCase(o.getLimitSwitch())).collect(Collectors.toList());
        InventoryAllotLineDTO inventoryAllotLineDTO=inventoryAllotLineGroup.get(0);
        InventoryAllotSDO inventoryAllotSDO = new InventoryAllotSDO();
        inventoryAllotSDO.setDistributionId(manualDistributionId);
        inventoryAllotSDO.setLimitSwitch(Boolean.FALSE);

        if (CollectionUtils.isNotEmpty(limitList)){
            inventoryAllotSDO.setLimitSwitch(Boolean.TRUE);
        }
        try {
            Date allotDate = strToDate(inventoryAllotLineDTO.getInventoryAllotDate());
            inventoryAllotSDO.setInventoryAllotTime(allotDate);
            inventoryAllotSDO.setDailyBeginTime(inventoryAllotLineDTO.getDailyBeginTime());
            inventoryAllotSDO.setDailyEndTime(inventoryAllotLineDTO.getDailyEndTime());
            inventoryAllotSDO.setInventoryAllotDate(inventoryAllotLineDTO.getInventoryAllotDate());
            DateTime dt = new DateTime();
            inventoryAllotSDO.setValidBeginTime(dt.millisOfDay().withMinimumValue().toDateTime().toDate());
            inventoryAllotSDO.setValidEndTime(dt.millisOfDay().withMaximumValue().toDateTime().toDate());
            inventoryAllotSDO.setDistributionType(getTypeByDistributionTypeDesc(inventoryAllotLineDTO.getDistributionType()));

        }catch (Exception e){
            log.error("Date format exception,dateStr={}",inventoryAllotLineDTO.getInventoryAllotDate());
        }

        OrganizationSDO salesOrganizationSDO = salesOrganizationInfoMap.get(
                inventoryAllotLineDTO.getOrganizationCode());
        if (salesOrganizationSDO != null) {
            //salesOrganizationSDO的code是外部编码，这个会影响页面可见性
            inventoryAllotSDO.setOrganizationCode(salesOrganizationSDO.getId());
            inventoryAllotSDO.setOrganizationName(salesOrganizationSDO.getName());
        }

        List<InventoryAllotLineSDO> inventoryAllotLineSDOS = new ArrayList<>();
        List<String> wareHouseOutCodes = new ArrayList<>();
        for (InventoryAllotLineDTO manualInventoryAllotLine : inventoryAllotLineGroup) {
            InventoryAllotLineSDO inventoryAllotLineSDO = new InventoryAllotLineSDO();
            // 外部仓库编码
            if (StringUtils.isNotBlank(manualInventoryAllotLine.getWarehouseOutCode())) {
                String warehouseOutCode = manualInventoryAllotLine.getWarehouseOutCode();
                wareHouseOutCodes.addAll(Arrays.asList(warehouseOutCode.split(COMMA)));
            }
            //外部货品编码转换
            ScItemSDO scItemSDO = scItemMap.get(manualInventoryAllotLine.getScItemId());
            if (scItemSDO != null) {
                inventoryAllotLineSDO.setScItemId(scItemSDO.getScItemId());
                inventoryAllotLineSDO.setScItemName(scItemSDO.getTitle());
                Map<String,Object> features = new HashMap<>();
                features.put("sc_item_outer_id",scItemSDO.getOuterId());
                features.put("dimension_out_id", manualInventoryAllotLine.getDimensionCode());
                features.put("is_manual","true");
                inventoryAllotLineSDO.setFeatures(JSON.toJSONString(features));
                //FIXME unitName读取到的是PC，unit是件
                inventoryAllotLineSDO.setInventoryUnit(scItemSDO.getUnit());
            }

            ChannelSDO channelSDO = channelInfoMap.get(
                    manualInventoryAllotLine.getDimensionCode());
            if(channelSDO!=null) {
                inventoryAllotLineSDO.setDimensionName(channelSDO.getChannelName());
                inventoryAllotLineSDO.setDimensionId(channelSDO.getChannelCode());
            }
            OrganizationSDO  organizationSDO = organizationInfoMap.get(
                    manualInventoryAllotLine.getDimensionCode());
            if(organizationSDO!=null) {
                inventoryAllotLineSDO.setDimensionName(organizationSDO.getName());
                inventoryAllotLineSDO.setDimensionId(organizationSDO.getId());
            }
            EmployeeSDO  employeeSDO = salesmanMap.get(
                    manualInventoryAllotLine.getDimensionCode());
            if(employeeSDO!=null) {
                inventoryAllotLineSDO.setDimensionName(employeeSDO.getName());
                inventoryAllotLineSDO.setDimensionId(employeeSDO.getId());
            }

            inventoryAllotLineSDO.setDistributionQuantity(manualInventoryAllotLine.getDistributionQuantity());
            // 剩余数量
            inventoryAllotLineSDO.setRemainingQuantity(manualInventoryAllotLine.getDistributionQuantity());
            inventoryAllotLineSDOS.add(inventoryAllotLineSDO);
        }
        inventoryAllotSDO.setFeatures(parseWareHouseIds(wareHouseOutCodes));
        inventoryAllotSDO.setInventoryAllotLineSDOS(inventoryAllotLineSDOS);
        return inventoryAllotSDO;
    }

    private String parseWareHouseIds(List<String> wareHouseOutCodes) {
        Map<String, String> map = new HashMap<>();
        if (CollectionUtils.isEmpty(wareHouseOutCodes)) {
            return JSONObject.toJSONString(map);
        }
        CargoZoneByOutCodesRequest request = new CargoZoneByOutCodesRequest();
        request.setCodes(wareHouseOutCodes);
        SearchCargoZoneListByOutCodeResponse response = unifiedInventoryService.searchCargoZoneListByOutCode(request);
        if (Objects.isNull(response) || CollectionUtils.isEmpty(response.getResult())) {
            return JSONObject.toJSONString(map);
        }
        List<String> list = new ArrayList<>();
        List<WarehouseInfo> result = response.getResult();
        result.forEach(warehouseInfo -> {
            list.add(warehouseInfo.getId());
        });
        map.put(WAREHOUSE_IDS, JSONObject.toJSONString(list));
        return JSONObject.toJSONString(map);
    }


    private  Date strToDate(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat(DateUtils.DATE_FORMAT);
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDate, pos);
    }


    private Result<Boolean> validateInventoryAllotGroup( List<InventoryAllotLineDTO> inventoryAllotLineGroup,
                                          Map<String, OrganizationSDO> salesOrganizationInfoMap,
                                          Map<String, ChannelSDO> channelInfoMap,
                                          Map<String, OrganizationSDO> organizationInfoMap,
                                          Map<String, EmployeeSDO> salesmanMap,
                                          Map<String, ScItemSDO> scItemMap){
        //暂时不判断分配单标识是否重复
        for(InventoryAllotLineDTO inputInventoryAllotLineDTO:inventoryAllotLineGroup) {
            if (StringUtils.isNotBlank(inputInventoryAllotLineDTO.getDistributionId())
                    && !inputInventoryAllotLineDTO.getDistributionId().startsWith(MANUAL_IMPORT_FLAG)) {
                appendErrorMessage(inputInventoryAllotLineDTO,"分配单标识号需按照M开头");
                return Result.fail("VALIDATE_FAILED","分配单标识号需按照M开头;部分失败导致整组失败;");
            }
            Result<String> validateResult = validateInventoryAllotLine(inputInventoryAllotLineDTO,false,salesOrganizationInfoMap,channelInfoMap,organizationInfoMap,salesmanMap,scItemMap);

            if (!validateResult.isSuccess()) {
                return Result.fail("VALIDATE_FAILED","部分失败导致整组失败;"+validateResult.getMessage());
            }
        }
        return Result.success(true);
    }

    private Optional<InventoryAllotLine> findInventoryAllotLine(
            InventoryAllotLineDTO inputInventoryAllotLineDTO,
            Map<String, ScItemSDO> scItemMap,
            Map<String, ChannelSDO> channelInfoMap,
            Map<String, OrganizationSDO> organizationInfoMap) {

        ScItemSDO innerScItemSDO = scItemMap.get(inputInventoryAllotLineDTO.getScItemId());
        if(innerScItemSDO==null){
            return Optional.empty();
        }

        final String innerDimensionCode =
                getInnerDimensionCode(inputInventoryAllotLineDTO, channelInfoMap, organizationInfoMap);
        if (StringUtils.isBlank(innerDimensionCode)) {
            return Optional.empty();
        }

        InventoryAllotLineLoadListRequest request = new InventoryAllotLineLoadListRequest();
        request.setInventoryAllotId(inputInventoryAllotLineDTO.getId());
        request.setDimensionId(innerDimensionCode);
        String innerScItemId=innerScItemSDO.getScItemId();
        request.setScItemIdList(Lists.newArrayList(innerScItemId));
        Result<List<InventoryAllotLine>> listResult = inventoryAllotLineService.loadInventoryAllotLineList(request);
        if (listResult!=null&&CollectionUtils.isNotEmpty(listResult.getResult())) {
            return Optional.of(listResult.getResult().get(0));
        }

        return Optional.empty();

    }

    private String getInnerDimensionCode(InventoryAllotLineDTO inputInventoryAllotLineDTO, Map<String, ChannelSDO> channelInfoMap,
                                         Map<String, OrganizationSDO> organizationInfoMap) {
        String dimensionType=inputInventoryAllotLineDTO.getDimensionType();
        if(dimensionType.equals(DimensionTypeEnum.CHANNEL.getCode())){
            ChannelSDO channelSDO = channelInfoMap.get(inputInventoryAllotLineDTO.getDimensionCode());
            if(channelSDO!=null) {
                return channelSDO.getChannelCode();
            }
        }else if(dimensionType.equals(DimensionTypeEnum.DEPARTMENT.getCode())){
            OrganizationSDO organizationSDO = organizationInfoMap.get(inputInventoryAllotLineDTO.getDimensionCode());
            if(organizationSDO!=null) {
                return organizationSDO.getId();
            }
        }else if(dimensionType.equals(DimensionTypeEnum.SALESMAN.getCode())){
            return inputInventoryAllotLineDTO.getDimensionCode();
        }
        return null;
    }

    private boolean adjustInventoryAllotDistributionQty(InventoryAllotLineDTO inputInventoryAllotLineDTO,
                                                        Map<String, ScItemSDO> scItemMap,
                                                        Map<String, ChannelSDO> channelInfoMap,
                                                        Map<String, OrganizationSDO> organizationInfoMap
    ) {

        Optional<InventoryAllotLine> inventoryAllotLineOp = findInventoryAllotLine(
                inputInventoryAllotLineDTO, scItemMap, channelInfoMap, organizationInfoMap);
        if (inventoryAllotLineOp.isPresent()) {
            //只修改数量
            UpdateDistributionQuantityRequest updateDistributionQuantityRequest
                    = new UpdateDistributionQuantityRequest();
            updateDistributionQuantityRequest.setId(String.valueOf(inventoryAllotLineOp.get().getId()));
            updateDistributionQuantityRequest.setDistributionQuantity(
                    inputInventoryAllotLineDTO.getDistributionQuantity());
            inventoryAllotLineWriteService.updateDistributionQuantity(updateDistributionQuantityRequest);
            return true;

        }else{
            return false;
        }
    }


    private Result<String> validateInventoryAllotLine(InventoryAllotLineDTO inputInventoryAllotLineDTO,boolean isAdjustInventoryAllotLine,
                                                      Map<String, OrganizationSDO> salesOrganizationInfoMap,
                                                      Map<String, ChannelSDO> channelInfoMap,
                                                      Map<String, OrganizationSDO> organizationInfoMap,
                                                      Map<String, EmployeeSDO> salesmanMap,
                                                      Map<String, ScItemSDO> scItemMap){
        //基础校验
        Result<String> validateResult = basicValidateInventoryAllotLine(inputInventoryAllotLineDTO,isAdjustInventoryAllotLine);
        if (!validateResult.isSuccess()) {
            return Result.fail(validateResult.getErrorCode(),validateResult.getMessage());
        }
        //业务校验
        Result<String> businessValidateResult = businessValidateInventoryAllotLine(inputInventoryAllotLineDTO,salesOrganizationInfoMap,channelInfoMap,organizationInfoMap,salesmanMap,scItemMap);
        if (!businessValidateResult.isSuccess()) {
            return Result.fail(businessValidateResult.getErrorCode(),businessValidateResult.getMessage());
        }
        return Result.success(null);
    }

    private Result<String> basicValidateInventoryAllotLine(InventoryAllotLineDTO inputInventoryAllotLineDTO,
                                                           boolean isAdjustInventoryAllotLine) {
        StringBuilder builder = new StringBuilder();

        if (!isAdjustInventoryAllotLine) {
            if (StringUtils.isBlank(inputInventoryAllotLineDTO.getWarehouseOutCode())) {
                builder.append("逻辑仓库编码code不能为空");
                builder.append(";");
            }
        }
        if (isAdjustInventoryAllotLine) {
            if (StringUtils.isBlank(inputInventoryAllotLineDTO.getId())) {
                builder.append("分配单id不能为空");
                builder.append(";");
            }
        }else{
            if (StringUtils.isBlank(inputInventoryAllotLineDTO.getDistributionId())) {
                builder.append("分配单标识号不能为空");
                builder.append(";");
            }
        }

        if (StringUtils.isBlank(inputInventoryAllotLineDTO.getDistributionQuantity())) {
            builder.append("分配数量不能为空");
            builder.append(";");
        }
        if (StringUtils.isBlank(inputInventoryAllotLineDTO.getInventoryAllotDate())) {
            builder.append("库存分配日期不能为空");
            builder.append(";");
        }
        if (StringUtils.isBlank(inputInventoryAllotLineDTO.getDistributionType())) {
            builder.append("分配单类型不能为空");
            builder.append(";");
        }
        if (StringUtils.isBlank(inputInventoryAllotLineDTO.getOrganizationCode())) {
            builder.append("销售组织编码不能为空");
            builder.append(";");
        }
        if (StringUtils.isBlank(inputInventoryAllotLineDTO.getDimensionCode())) {
            builder.append("维度编码不能为空");
            builder.append(";");
        }
        if (StringUtils.isBlank(inputInventoryAllotLineDTO.getScItemId())){
            builder.append("货品编码不能为空");
            builder.append(";");
        }
        if (StringUtils.isNotBlank(inputInventoryAllotLineDTO.getDistributionType())) {
            try {
                getTypeByDistributionTypeDesc(inputInventoryAllotLineDTO.getDistributionType());
            }catch (RuntimeException e){
                builder.append("分配单类型填写不正确");
                builder.append(";");
            }
        }

        String errorMessage = builder.toString();
        if (StringUtils.isNotBlank(errorMessage)) {
            return Result.fail("BASIC_VALIDATE_FAILED", builder.toString());
        }
        return Result.success(null);

    }

    private Result<String> businessValidateInventoryAllotLine(InventoryAllotLineDTO inputInventoryAllotLineDTO,
                                                              Map<String, OrganizationSDO> salesOrganizationInfoMap,
                                                              Map<String, ChannelSDO> channelInfoMap,
                                                              Map<String, OrganizationSDO> departmentInfoMap,
                                                              Map<String, EmployeeSDO> salesmanMap,
                                                              Map<String, ScItemSDO> scItemMap) {

        StringBuilder builder = new StringBuilder();
        //分配和调整场景，货品编码必须要存在
        if (scItemMap.get(inputInventoryAllotLineDTO.getScItemId()) == null) {
            builder.append(inputInventoryAllotLineDTO.getScItemId());
            builder.append("货品编码不存在");
            builder.append(";");
        }

        if(StringUtils.isNotBlank(inputInventoryAllotLineDTO.getDistributionId())){
            //手工分配的场景
            if(inputInventoryAllotLineDTO.getDistributionId().startsWith(MANUAL_IMPORT_FLAG)){

                if (salesOrganizationInfoMap.get(inputInventoryAllotLineDTO.getOrganizationCode()) == null) {
                    builder.append("销售组织编码不存在");
                    builder.append(";");
                }
                String dimensionType=getTypeByDistributionTypeDesc(inputInventoryAllotLineDTO.getDistributionType());
                if(StringUtils.isNotBlank(dimensionType)) {
                    if (dimensionType.equals(DimensionTypeEnum.CHANNEL.getCode()) && channelInfoMap.get(
                            inputInventoryAllotLineDTO.getDimensionCode())
                            == null) {
                        builder.append("渠道维度编码不存在");
                        builder.append(";");
                    }else if(dimensionType.equals(DimensionTypeEnum.DEPARTMENT.getCode()) && departmentInfoMap.get(
                            inputInventoryAllotLineDTO.getDimensionCode()) == null){
                        builder.append("部门维度编码不存在");
                        builder.append(";");
                    }
                    else if(dimensionType.equals(DimensionTypeEnum.SALESMAN.getCode()) && salesmanMap.get(
                        inputInventoryAllotLineDTO.getDimensionCode()) == null){
                        builder.append("业务员维度编码不存在");
                        builder.append(";");
                    }
                }
            }
        }

        String errorMessage = builder.toString();
        if (StringUtils.isNotBlank(errorMessage)) {
            return Result.fail("BUSINESS_VALIDATE_FAILED", builder.toString());
        }
        return Result.success(null);

    }


    private void enrichInventoryAllotLineDTOList(List<InventoryAllotLineDTO> inventoryAllotLineDTOList) {
        int lineNo = 1;
        for (InventoryAllotLineDTO inventoryAllotLineDTO : inventoryAllotLineDTOList) {
            try {
                if(StringUtils.isEmpty(inventoryAllotLineDTO.getDimensionType())) {
                    inventoryAllotLineDTO.setDimensionType(
                            getTypeByDistributionTypeDesc(inventoryAllotLineDTO.getDistributionType()));
                }
            } catch (Exception e) {
                log.error("distributeType cannot be identified and ignored,inventoryAllotLineDTO={}",
                        JSON.toJSONString(inventoryAllotLineDTO));
            }

            inventoryAllotLineDTO.setIndex(lineNo);
            lineNo++;
        }
    }

    private String getTypeByDistributionTypeDesc(String  distributionType) {

        if(distributionType.equalsIgnoreCase(InventoryAllotTypeEnum.DEPARTMENT.getDesc())){
            return DimensionTypeEnum.DEPARTMENT.getCode();
        }else if(distributionType.equalsIgnoreCase(InventoryAllotTypeEnum.CHANNEL.getDesc())){
            return DimensionTypeEnum.CHANNEL.getCode();
        }
        else if(distributionType.equalsIgnoreCase(InventoryAllotTypeEnum.SALESMAN.getDesc())){
            return DimensionTypeEnum.SALESMAN.getCode();
        }
        throw new RuntimeException("分配单类型无法识别");
    }


    private boolean isInventoryAllotIdExist( Map<String,Boolean> inventoryAllotIdMap,String id,Boolean limit){

        if(inventoryAllotIdMap.get(id)!=null){
            if(inventoryAllotIdMap.get(id).equals(Boolean.TRUE)){
                return true;
            }
        }
        LoadRequest loadRequest = new LoadRequest();
        loadRequest.setId(Long.parseLong(id));
        try {
            InventoryAllot load = inventoryAllotService.load(loadRequest);
            if(load!=null){
                load.setLimitSwitch(limit);
                inventoryAllotService.update(load);
                return true;
            }
        }catch (Exception e){
            //纪元可能抛出异常
            log.error("inventoryAllotService.load exception,id={}",id);
        }
        return false;

    }

    /**
     * 部门、渠道、销售组织都抽象为组织
     * 销售组织读取OrganizationCode，通过类型0区分
     * 维度code读取DimensionCode，通过类型1区分
     */
    private Map<String, ChannelSDO> getBusinessChannelInfoMap(List<InventoryAllotLineDTO> inventoryAllotLineDTOList) {

        Map<String, ChannelSDO> businessChannelInfoMap = Maps.newHashMap();

        List<String> outCodes = inventoryAllotLineDTOList.stream().map(InventoryAllotLineDTO::getDimensionCode)
                .distinct().collect(Collectors.toList());

        if (CollectionUtils.isEmpty(outCodes)) {
            return businessChannelInfoMap;
        }
        //批量查询
        BaselineBatchQueryChannels2Request request = new BaselineBatchQueryChannels2Request();
        request.setOutCodes(outCodes);
        Result<List<ChannelSDO>> channelQueryResult
                = baseDataService.baselineBatchQueryChannels2(request);
        if (channelQueryResult != null && channelQueryResult.isSuccess()) {
            List<ChannelSDO> channelSDOList
                    = channelQueryResult.getResult();
            if (CollectionUtils.isNotEmpty(channelSDOList)) {
                businessChannelInfoMap= channelSDOList.stream().collect(
                        Collectors.toMap(ChannelSDO::getOutCode,
                                Function.identity()));
            }
        }
        return businessChannelInfoMap;

    }

//baselineGetEmployeeByIdsAll
private Map<String, EmployeeSDO> getSalesmanMap(List<InventoryAllotLineDTO> inventoryAllotLineDTOList) {
    Map<String, EmployeeSDO> organizationInfoMap = Maps.newHashMap();
    List<String> employIds = Lists.newArrayList();
    //销售组织
    employIds = inventoryAllotLineDTOList.stream().map(InventoryAllotLineDTO::getDimensionCode)
                .distinct().collect(Collectors.toList());
    if (CollectionUtils.isEmpty(employIds)) {
        return organizationInfoMap;
    }
    //批量查询
    BaselineGetEmployeeByIdsAllRequest request = new BaselineGetEmployeeByIdsAllRequest();
    request.setIds(employIds);
    request.setStatus(1);
    Result<List<EmployeeSDO>> employeeByIdsAll
            = baseDataService.baselineGetEmployeeByIdsAll(request);
    if (employeeByIdsAll != null && CollectionUtils.isNotEmpty(employeeByIdsAll.getResult())) {
        List<EmployeeSDO> employeeSDOList
                = employeeByIdsAll.getResult();
        if (CollectionUtils.isNotEmpty(employeeSDOList)) {
            organizationInfoMap= employeeSDOList.stream().collect(
                    Collectors.toMap(EmployeeSDO::getId,
                            Function.identity()));
        }
    }
    return organizationInfoMap;

}

    /**
     * 部门、渠道、销售组织都抽象为组织
     * 销售组织读取OrganizationCode，通过类型0区分
     * 维度code读取DimensionCode，通过类型1区分
     */
    private Map<String, OrganizationSDO> getOrganizationInfoMap(List<InventoryAllotLineDTO> inventoryAllotLineDTOList,int codeType) {
        Map<String, OrganizationSDO> organizationInfoMap = Maps.newHashMap();
        List<String> outCodes = Lists.newArrayList();
        //销售组织
        if (codeType == 0) {
            outCodes = inventoryAllotLineDTOList.stream().map(InventoryAllotLineDTO::getOrganizationCode)
                    .distinct().collect(Collectors.toList());
        } else if (codeType == 1) {
            outCodes = inventoryAllotLineDTOList.stream().map(InventoryAllotLineDTO::getDimensionCode)
                    .distinct().collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(outCodes)) {
            return organizationInfoMap;
        }
        //批量查询
        BaselineGetOrganizationByOutCodes2Request request = new BaselineGetOrganizationByOutCodes2Request();
        request.setOutCodes(outCodes);
        BaselineGetOrganizationByOutCodes2Response organizationResponse
                = baseDataService.baselineGetOrganizationByOutCodes2(request);
        if (organizationResponse != null && organizationResponse.getSuccess()) {
            List<OrganizationSDO> organizationSDOList
                    = organizationResponse.getResult();
            if (CollectionUtils.isNotEmpty(organizationSDOList)) {
                organizationInfoMap= organizationSDOList.stream().collect(
                        Collectors.toMap(OrganizationSDO::getOutCode,
                                Function.identity()));
            }
        }
        return organizationInfoMap;

    }

    private Map<String,ScItemSDO> getScItemMap(List<String> scItemIds) {
        Map<String,ScItemSDO> scItemMap= Maps.newHashMap();
        //外部货品编码转换
        SearchScItemRequest scItemRequest = new SearchScItemRequest();
        JSONObject searchReqDTO = new JSONObject();
        searchReqDTO.put("outerIdList", scItemIds);
        searchReqDTO.put("businessType","11");//业态常温
        searchReqDTO.put("type",0);//非组合货品
        scItemRequest.setSearchReqDTO(searchReqDTO);
        scItemRequest.setPageNum(1);
        scItemRequest.setPageSize(scItemIds.size());
        Result<List<ScItemSDO>> scItemQueryResult = baseDataService.searchScItem(scItemRequest);
        if(scItemQueryResult!=null&&scItemQueryResult.isSuccess()){
            List<ScItemSDO> scItemSDOList=scItemQueryResult.getResult();
            if(CollectionUtils.isNotEmpty(scItemSDOList)){
                scItemMap =scItemSDOList.stream().collect(Collectors.toMap(ScItemSDO::getOuterId, Function.identity()));
            }
        }else{
            log.error("searchScItem exception,scItemRequest={}",JSON.toJSONString(scItemRequest));
        }
        return scItemMap;

    }

    @Override
    public Result<Boolean> excelImport(InventoryAllotExcelImportRequest request) {
        //删除无效代码
        return Result.success(true);
    }

    @Override
    public Result<Boolean> deleteById(DeleteInventoryAllotByIdRequest deleteInventoryAllotByIdRequest) {
        InventoryAllotEntity inventoryAllotEntity = InventoryAllotFactory.deleteById(deleteInventoryAllotByIdRequest);
        inventoryAllotEntity.delete();
        return Result.success(true);
    }



    /**
     * 查询回复计划策略
     *
     * @param inventoryAllotDetail
     * @return
     */
    private DimensionSDO getDimensionSDO(InventoryAllotDetail inventoryAllotDetail) {
        StrategyPageQueryRequest request = new StrategyPageQueryRequest();
        request.setType(StrategyTypeEnum.REPLY_COMPUTE.getCode());
        request.setOrganizationCode(inventoryAllotDetail.getOrgId());
        Result<List<StrategyPageQueryResponse>> result = strategyQueryService.pageQuery(request);
        if (CollectionUtils.isEmpty(result.getResult())) {
            throw new FunctionException("OTS-05-001-10-16-019");
        }
        StrategyPageQueryResponse strategyPageQueryResponse = result.getResult().get(0);
        StrategyQueryByIdRequest queryByIdRequest = new StrategyQueryByIdRequest();
        queryByIdRequest.setId(strategyPageQueryResponse.getId());
        Result<StrategyQueryByIdResponse> result1 = strategyQueryService.queryById(queryByIdRequest);
        DimensionSDO dimensionSDO = result1.getResult().getStrategySDO().getDimensionSDOList().get(0);
        return dimensionSDO;
    }

    /**
     * 渠道查询月度计划
     *
     * @param inventoryAllotDetail
     * @param
     * @return
     */
    private SalesPlanStatScItemSDO channelGetSalesPlanStatScItemSDO(InventoryAllotDetail inventoryAllotDetail, String scItemId, String saleChannelId) {
        PageQueryPlanScItemStatRequest pageQueryPlanScItemStatRequest = new PageQueryPlanScItemStatRequest();
        pageQueryPlanScItemStatRequest.setPlanId(queryParentId(inventoryAllotDetail.getOrgId()));
        pageQueryPlanScItemStatRequest.setPoolType(StatPoolTypeEnum.SC_ITEM.getPoolType());
        pageQueryPlanScItemStatRequest.setBizId(saleChannelId);
        pageQueryPlanScItemStatRequest.setBizType(SalesStatBizTypeEnum.SALES_CHANNEL.getOrganizationType());
        pageQueryPlanScItemStatRequest.setScItemId(scItemId);
        Result<PageResult<List<SalesPlanStatScItemSDO>>> pageResultResult = salesPlanScItemStatQueryService.pageQueryPlanScItemList(pageQueryPlanScItemStatRequest);
        log.info("销售渠道:" + saleChannelId + "渠道月度结果:" + JSON.toJSONString(pageResultResult));
        if (CollectionUtils.isEmpty(pageResultResult.getResult().getContent())) {
            //throw new FunctionException("OTS-05-001-10-16-016");
            return null;
        }
        SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageResultResult.getResult().getContent().get(0);
        return salesPlanStatScItemSDO;
    }

    private List<SalesPlanStatScItemSDO> batchChannelGetSalesPlanStatScItemSDO(InventoryAllotDetail inventoryAllotDetail, String scItemId, List<String> saleChannelIds) {
        QueryPlanScItemStatRequest pageQueryPlanScItemStatRequest = new QueryPlanScItemStatRequest();
        pageQueryPlanScItemStatRequest.setPlanId(Long.valueOf(queryParentId(inventoryAllotDetail.getOrgId())));
        pageQueryPlanScItemStatRequest.setPoolType(String.valueOf(StatPoolTypeEnum.SC_ITEM.getPoolType()));
        pageQueryPlanScItemStatRequest.setBizIds(saleChannelIds);
        pageQueryPlanScItemStatRequest.setBizType(SalesStatBizTypeEnum.SALES_CHANNEL.getBizType());
        //@todo 不传scItemIds 根据返回结果去get
        pageQueryPlanScItemStatRequest.setScItemId(scItemId);
        Result<PageResult<List<SalesPlanStatScItemSDO>>> pageResultResult = salesPlanScItemStatQueryService.batchQueryPlanScItemByBizId(pageQueryPlanScItemStatRequest);
        log.info("销售渠道:" + JSON.toJSONString(saleChannelIds) + "渠道月度结果:" + JSON.toJSONString(pageResultResult));
        if (Objects.isNull(pageResultResult)||Objects.isNull(pageResultResult.getResult())||CollectionUtils.isEmpty(pageResultResult.getResult().getContent())) {
            //throw new FunctionException("OTS-05-001-10-16-016");
            return null;
        }

        return pageResultResult.getResult().getContent();
    }


    private Map<String, Map<String, List<SalesPlanStatScItemSDO>>> batchGetSalesPlanStatScItemSDOAll(InventoryAllotDetail inventoryAllotDetail, List<String> dimensionList,Integer bizType) {
        QueryPlanScItemStatRequest pageQueryPlanScItemStatRequest = new QueryPlanScItemStatRequest();
        String planId = queryParentId(inventoryAllotDetail.getOrgId());
        if (StringUtils.isBlank(planId)){
            return new HashMap<>();
        }
        pageQueryPlanScItemStatRequest.setPlanId(Long.valueOf(planId));
        pageQueryPlanScItemStatRequest.setPoolType(String.valueOf(StatPoolTypeEnum.SC_ITEM.getPoolType()));
        pageQueryPlanScItemStatRequest.setBizIds(dimensionList);
        pageQueryPlanScItemStatRequest.setBizType(bizType);
        pageQueryPlanScItemStatRequest.setStart(0);
        pageQueryPlanScItemStatRequest.setLimit(1000);
        //@todo 不传scItemIds 根据返回结果去get
       // pageQueryPlanScItemStatRequest.setScItemId(scItemId);
        Result<PageResult<List<SalesPlanStatScItemSDO>>> firstResult = salesPlanScItemStatQueryService.batchQueryPlanScItemByBizId(pageQueryPlanScItemStatRequest);


        if (Objects.isNull(firstResult)||Objects.isNull(firstResult.getResult())||CollectionUtils.isEmpty(firstResult.getResult().getContent())) {
            //throw new FunctionException("OTS-05-001-10-16-016");
            return new HashMap<>();
        }
        List<SalesPlanStatScItemSDO> totalResult=new ArrayList<>();
        int total = firstResult.getTotal();
        if (total>1000){
            int page = total / 1000;
            for (int i = 0; i <= page; i++) {
                pageQueryPlanScItemStatRequest.setStart(i*1000);
                pageQueryPlanScItemStatRequest.setLimit(1000);
                Result<PageResult<List<SalesPlanStatScItemSDO>>> resultResult = salesPlanScItemStatQueryService.batchQueryPlanScItemByBizId(pageQueryPlanScItemStatRequest);
                if (Objects.nonNull(resultResult)&&Objects.nonNull(resultResult.getResult())&&CollectionUtils.isNotEmpty(resultResult.getResult().getContent())) {
                    totalResult.addAll(resultResult.getResult().getContent());
                }
            }

        }else {
            totalResult.addAll(firstResult.getResult().getContent());
        }

        log.info("销售渠道:" + JSON.toJSONString(dimensionList) + "渠道月度结果:" + JSON.toJSONString(totalResult));
        Map<String, Map<String, List<SalesPlanStatScItemSDO>>> scItemMapMap=new HashMap<>();
        Map<String, List<SalesPlanStatScItemSDO>> collect = Nullable.stream(totalResult).collect(Collectors.groupingBy(SalesPlanStatScItemSDO::getScItemId));
        for (Entry<String, List<SalesPlanStatScItemSDO>> entry:collect.entrySet()){

            if (CollectionUtils.isNotEmpty(entry.getValue())){
                Map<String, List<SalesPlanStatScItemSDO>> bizIdMap = entry.getValue().stream().collect(Collectors.groupingBy(SalesPlanStatScItemSDO::getBizId));
                scItemMapMap.put(entry.getKey(),bizIdMap);
            }
        }

        return scItemMapMap;
    }

    private SalesPlanStatScItemSDO salesmanGetSalesPlanStatScItemSDO(InventoryAllotDetail inventoryAllotDetail, SalesmanScope salesmanScope, String itemId) {
        PageQueryPlanScItemStatRequest pageQueryPlanScItemStatRequest = new PageQueryPlanScItemStatRequest();
        pageQueryPlanScItemStatRequest.setPlanId(queryParentId(inventoryAllotDetail.getOrgId()));
        pageQueryPlanScItemStatRequest.setPoolType(StatPoolTypeEnum.SC_ITEM.getPoolType());
        pageQueryPlanScItemStatRequest.setScItemId(itemId);
        pageQueryPlanScItemStatRequest.setBizId(salesmanScope.getSalesmanId());
        pageQueryPlanScItemStatRequest.setBizType(SalesStatBizTypeEnum.SALESMAN.getOrganizationType());
        Result<PageResult<List<SalesPlanStatScItemSDO>>> pageResultResult = salesPlanScItemStatQueryService.pageQueryPlanScItemList(pageQueryPlanScItemStatRequest);
        log.info("库存分解-业务员月度计划查询：" + JSON.toJSONString(pageResultResult));
        if (Objects.isNull(pageResultResult)||Objects.isNull(pageResultResult.getResult())||CollectionUtils.isEmpty(pageResultResult.getResult().getContent())) {
            //throw new FunctionException("OTS-05-001-10-16-018");
            return null;
        }
        SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageResultResult.getResult().getContent().get(0);
        return salesPlanStatScItemSDO;
    }

    private Map<String, SalesPlanStatScItemSDO> batchSalesmanGetSalesPlanStatScItemSDO(InventoryAllotDetail inventoryAllotDetail, List<SalesmanScope> salesmanScope, String scItemId) {
        List<String> salesmenIds = Nullable.stream(salesmanScope).map(SalesmanScope::getSalesmanId).collect(Collectors.toList());
        QueryPlanScItemStatRequest pageQueryPlanScItemStatRequest = new QueryPlanScItemStatRequest();
        pageQueryPlanScItemStatRequest.setPlanId(Long.valueOf(queryParentId(inventoryAllotDetail.getOrgId())));
        pageQueryPlanScItemStatRequest.setPoolType(String.valueOf(StatPoolTypeEnum.SC_ITEM.getPoolType()));
        pageQueryPlanScItemStatRequest.setBizIds(salesmenIds);
        pageQueryPlanScItemStatRequest.setBizType(SalesStatBizTypeEnum.SALESMAN.getBizType());
        pageQueryPlanScItemStatRequest.setScItemId(scItemId);
        //  try {
        Result<PageResult<List<SalesPlanStatScItemSDO>>> pageResultResult =  salesPlanScItemStatQueryService.batchQueryPlanScItemByBizId(pageQueryPlanScItemStatRequest);

        log.info("库存分解-批量业务员月度计划查询：" + JSON.toJSONString(pageResultResult));
        if (Objects.isNull(pageResultResult)||Objects.isNull(pageResultResult.getResult())||CollectionUtils.isEmpty(pageResultResult.getResult().getContent())) {
            //throw new FunctionException("OTS-05-001-10-16-018");
            return null;
        }
        Map<String, SalesPlanStatScItemSDO> planStatScItemSDOMap = Nullable.stream(pageResultResult.getResult().getContent()).collect(Collectors.toMap(SalesPlanStatScItemSDO::getBizId, Function.identity()));
        return planStatScItemSDOMap;
    }

    private SalesPlanStatScItemSDO departmentGetSalesPlanStatScItemSDO(InventoryAllotDetail inventoryAllotDetail, DepartmentScope departmentScope, String scItemId) {
        PageQueryPlanScItemStatRequest pageQueryPlanScItemStatRequest = new PageQueryPlanScItemStatRequest();
        pageQueryPlanScItemStatRequest.setPlanId(queryParentId(inventoryAllotDetail.getOrgId()));
        pageQueryPlanScItemStatRequest.setPoolType(StatPoolTypeEnum.SC_ITEM.getPoolType());
        pageQueryPlanScItemStatRequest.setBizId(departmentScope.getDepartmentId());
        pageQueryPlanScItemStatRequest.setBizType(SalesStatBizTypeEnum.SALES_DEPARTMENT.getOrganizationType());
        pageQueryPlanScItemStatRequest.setScItemId(scItemId);
        try {
            Result<PageResult<List<SalesPlanStatScItemSDO>>> pageResultResult = salesPlanScItemStatQueryService.pageQueryPlanScItemList(pageQueryPlanScItemStatRequest);
            log.info("库存分解-部门月度计划查询：" + JSON.toJSONString(pageResultResult));
            if(!pageResultResult.isSuccess()){
                throw new FunctionException(pageResultResult.getErrorCode(),pageResultResult.getMessage());
            }
            if (CollectionUtils.isEmpty(pageResultResult.getResult().getContent())) {
                //throw new FunctionException("OTS-05-001-10-16-017");
                return null;
            }
            SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageResultResult.getResult().getContent().get(0);
            return salesPlanStatScItemSDO;
        } catch (Exception e) {
            throw new FunctionException("OTS-05-001-10-16-017", departmentScope.getDepartmentName());
        }

    }

    private Map<String, SalesPlanStatScItemSDO> batchDepartmentGetSalesPlanStatScItemSDO(InventoryAllotDetail inventoryAllotDetail, List<DepartmentScope> departmentScope, String scItemId) {
        List<String> departmentCodes = Nullable.stream(departmentScope).map(DepartmentScope::getDepartmentId).collect(Collectors.toList());
        QueryPlanScItemStatRequest pageQueryPlanScItemStatRequest = new QueryPlanScItemStatRequest();
        pageQueryPlanScItemStatRequest.setPlanId(Long.valueOf(queryParentId(inventoryAllotDetail.getOrgId())));
        pageQueryPlanScItemStatRequest.setPoolType(String.valueOf(StatPoolTypeEnum.SC_ITEM.getPoolType()));
        pageQueryPlanScItemStatRequest.setBizIds(departmentCodes);
        pageQueryPlanScItemStatRequest.setBizType(SalesStatBizTypeEnum.SALES_DEPARTMENT.getBizType());
        pageQueryPlanScItemStatRequest.setScItemId(scItemId);
        try {
            Result<PageResult<List<SalesPlanStatScItemSDO>>> pageResultResult = salesPlanScItemStatQueryService.batchQueryPlanScItemByBizId(pageQueryPlanScItemStatRequest);
            log.info("库存分解-批量部门月度计划查询：" + JSON.toJSONString(pageResultResult));
            if (CollectionUtils.isEmpty(pageResultResult.getResult().getContent())) {
                //throw new FunctionException("OTS-05-001-10-16-017");
                return null;
            }
            Map<String, SalesPlanStatScItemSDO> planStatScItemSDOMap = Nullable.stream(pageResultResult.getResult().getContent()).collect(Collectors.toMap(SalesPlanStatScItemSDO::getBizId, Function.identity()));
            return planStatScItemSDOMap;
        } catch (Exception e) {
            throw new FunctionException("OTS-05-001-10-16-017", JSON.toJSONString(departmentScope));
        }

    }

    private List<InventoryAllotDetail> converterDetail(List<StrategySDO> strategySDOS) {
        List<InventoryAllotDetail> inventoryAllotDetails = new ArrayList<>();
        for (StrategySDO strategySDO : strategySDOS) {
            InventoryAllotDetail detail = new InventoryAllotDetail();
            detail.setDimensionType(strategySDO.getDimensionType());
            detail.setStrategyId(strategySDO.getId());
            detail.setOrgId(strategySDO.getOrganizationCode());
            detail.setOrgName(strategySDO.getOrganizationName());
            detail.setValidBeginTime(strategySDO.getValidBeginTime());
            detail.setValidEndTime(strategySDO.getValidEndTime());
            //页面按照比例由小数改为之前的100倍
            detail.setPercent(0.01*Double.parseDouble(strategySDO.getShare()));
            detail.setDailyBeginTime(strategySDO.getDailyBeginTime());
            detail.setDailyEndTime(strategySDO.getDailyEndTime());
            List<ScItemScope> scItemScopes = new ArrayList<>();
            List<WarehouseScope> warehouseScopes = new ArrayList<>();
            List<ChannelScope> channelScopes = new ArrayList<>();
            List<DepartmentScope> departmentScopes = new ArrayList<>();
            List<SalesmanScope> salesmanScopes = new ArrayList<>();
            Map<String, String> feature = new HashMap<>();
            for (DimensionSDO dimensionSDO : strategySDO.getDimensionSDOList()) {

                if (DimensionTypeEnum.GOODS.getCode().equals(dimensionSDO.getCode())) {
                    ScItemScope scItemScope = new ScItemScope();
                    scItemScope.setScItemId(dimensionSDO.getValue());
                    scItemScope.setScItemName(dimensionSDO.getValueName());
                    scItemScopes.add(scItemScope);
                }

                if (DimensionTypeEnum.STORE_ROOM.getCode().equals(dimensionSDO.getCode())) {
                    WarehouseScope warehouseScope = new WarehouseScope();
                    warehouseScope.setWarehouseId(dimensionSDO.getValue());
                    warehouseScope.setWarehouseName(dimensionSDO.getValueName());
                    warehouseScopes.add(warehouseScope);
                }
                //渠道
                if (DimensionTypeEnum.CHANNEL.getCode().equals(dimensionSDO.getCode())) {
                    ChannelScope channelScope = new ChannelScope();
                    channelScope.setChannelId(dimensionSDO.getValue());
                    channelScope.setChannelName(dimensionSDO.getValueName());
                    channelScopes.add(channelScope);
                }

                if (DimensionTypeEnum.DEPARTMENT.getCode().equals(dimensionSDO.getCode())) {
                    DepartmentScope departmentScope = new DepartmentScope();
                    departmentScope.setDepartmentId(dimensionSDO.getValue());
                    departmentScope.setDepartmentName(dimensionSDO.getValueName());
                    departmentScopes.add(departmentScope);
                }

                if (DimensionTypeEnum.SALESMAN.getCode().equals(dimensionSDO.getCode())) {
                    SalesmanScope salesmanScope = new SalesmanScope();
                    salesmanScope.setSalesmanId(dimensionSDO.getValue());
                    salesmanScope.setSalesmanName(dimensionSDO.getValueName());
                    salesmanScopes.add(salesmanScope);
                }
                detail.setScItemScopes(scItemScopes);
                detail.setWarehouseScopes(warehouseScopes);
                detail.setChannelScopes(channelScopes);
                detail.setDepartmentScopes(departmentScopes);
                detail.setSalesmanScopes(salesmanScopes);
                feature.put(dimensionSDO.getValue(),dimensionSDO.getOutCode());
                detail.setFeatures(feature);
            }
            inventoryAllotDetails.add(detail);
        }
        return inventoryAllotDetails;
    }

    public String queryParentId(String organizationCode) {
        PageQuerySalePlanRequest pageQuerySalePlanRequest = new PageQuerySalePlanRequest();
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        //设置当前月份
        pageQuerySalePlanRequest.setPlanTime(year + "-" + month);

        BaselineGetOrganizationByIdRequest request = new BaselineGetOrganizationByIdRequest();
        request.setId(organizationCode);
        Map map = (Map) baseDataService.baselineGetOrganizationById(request);
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(map));
        String s = jsonObject.getJSONObject("result").getJSONObject("result").getJSONObject("organizationSDO").getString("parentId");
        pageQuerySalePlanRequest.setOrgBusinessUnitCode(s);
        Result<PageResult<List<SalesPlanSDO>>> pageResultResult = salesPlanQueryService.pageQuerySalesPlanList(pageQuerySalePlanRequest);
        if (CollectionUtils.isNotEmpty(pageResultResult.getResult().getContent())) {
            return pageResultResult.getResult().getContent().get(0).getId().toString();
        }
        return null;
    }
}
